HHUOJ 1405 区间查询
题目描述
食堂有N个打饭窗口,现在正到了午饭时间,每个窗口都排了很多的学生,而且每个窗口排队的人数在不断的变化。
现在问你第i个窗口到第j个窗口一共有多少人在排队?
输入
输入的第一行是一个整数T,表示有T组测试数据。
每组输入的第一行是一个正整数N(N<=30000),表示食堂有N个窗口。
接下来一行输入N个正整数,第i个正整数ai表示第i个窗口最开始有ai个人排队。(1<=ai<=50)
接下来每行有一条命令,命令有四种形式:
(1)Add i j,i和j为正整数,表示第i个窗口增加j个人(j不超过30);
(2)Sub i j,i和j为正整数,表示第i个窗口减少j个人(j不超过30);
(3)Query i j,i和j为正整数,i<=j,表示询问第i到第j个窗口的总人数;
(4)End 表示结束,这条命令在每组数据最后出现;
每组数据最多有40000条命令。
输出
对于每组输入,首先输出样例号,占一行。
然后对于每个Query询问,输出一个整数,占一行,表示询问的段中的总人数,这个数保持在int以内。
样例输入
1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End
样例输出
Case 1:
6
33
59
我用线段树和树状数组都做了一下,线段树759ms,树状数组479ms,放上代码对比一下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int tree[120005];
void pushup(int i)
{
tree[i]=tree[2*i]+tree[2*i+1];
}
void build(int i,int l,int r)
{
if(l==r)
{
scanf("%d",&tree[i]);
return ;
}
int mid=l+(r-l)/2;
build(2*i,l,mid);
build(2*i+1,mid+1,r);
pushup(i);
}
void add(int i,int l,int r,int x,int k)
{
if(l==r && r==x)
{
tree[i]+=k;
return ;
}
int mid=l+(r-l)/2;
if(x<=mid) add(2*i,l,mid,x,k);
else add(2*i+1,mid+1,r,x,k);
pushup(i);
}
void sub(int i,int l,int r,int x,int k)
{
if(l==r && r==x)
{
tree[i]-=k;
return ;
}
int mid=l+(r-l)/2;
if(x<=mid) sub(2*i,l,mid,x,k);
else sub(2*i+1,mid+1,r,x,k);
pushup(i);
}
int query(int i,int l,int r,int x,int y)
{
if(x<=l && r<=y) return tree[i];
int ans=0,mid=l+(r-l)/2;
if(x<=mid) ans+=query(2*i,l,mid,x,y);
if(y>mid) ans+=query(2*i+1,mid+1,r,x,y);
return ans;
}
int main()
{
string s;
int t,n,x,y;
scanf("%d",&t);
for (int i=1;i<=t;i++)
{
printf("Case %d:\n",i);
scanf("%d",&n);
build(1,1,n);
while(true)
{
cin>>s;
if(s=="End") break;
if(s=="Query")
{
scanf("%d%d",&x,&y);
printf("%d\n",query(1,1,n,x,y));
}
else if (s=="Add")
{
scanf("%d%d",&x,&y);
add(1,1,n,x,y);
}
else if(s=="Sub")
{
scanf("%d%d",&x,&y);
sub(1,1,n,x,y);
}
}
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int bit[30005],a[30005];
int t,n,x,y;
int lowbit(int x)
{
return x&(-x);
}
void add(int i,int x)
{
while(i<=n)
{
bit[i]+=x;
i+=lowbit(i);
}
}
void sub(int i,int x)
{
while(i<=n)
{
bit[i]-=x;
i+=lowbit(i);
}
}
int sum(int i)
{
int s=0;
while(i>0)
{
s+=bit[i];
i-=lowbit(i);
}
return s;
}
int main()
{
scanf("%d",&t);
for(int j=1;j<=t;j++)
{
memset(a,0,sizeof(a));//一定要memset,否则WA
memset(bit,0,sizeof(bit));
printf("Case %d:\n",j);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(i,a[i]);
}
string s;
while(cin>>s)
{
if(s=="End") break;
else if(s=="Add") {scanf("%d%d",&x,&y); add(x,y);}
else if(s=="Sub") {scanf("%d%d",&x,&y); sub(x,y);}
else if(s=="Query") {scanf("%d%d",&x,&y); printf("%d\n",sum(y)-sum(x-1));}
}
}
return 0;
}
来源:https://blog.csdn.net/qq_43765333/article/details/96976654