Description
给你一个序列,然后会根据题意选择序列中的一个值增加或减少,或者询问某区间和
Input
第一行一个整数T,表示有T组数据。
每组数据第一行一个正整数N(N<=50000),表示敌人有N个工兵营地,接下来有N个正整数,第i个正整数ai代表第i个工兵营地里开始时有ai个人(1<=ai<=50)。
接下来每行有一条命令,命令有4种形式:
(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条命令
Output
对第i组数据,首先输出“Case i:”和回车,
对于每个Query询问,输出一个整数并回车,表示询问的段中的总人数,这个数保持在int以内
Sample Input
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
Sample Output
Case 1:
6
33
59
Solution
树状数组简单题,单点更新+区间查询
Code
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define maxn 55555
int t,n;
int a[maxn],b[maxn];
char c[10];
int sum(int i)//求前缀和
{
int s=0;
while(i>0)
{
s+=b[i];
i-=i&-i;
}
return s;
}
void add(int i,int v)//单点更新
{
while(i<=n)
{
b[i]+=v;
i+=i&-i;
}
}
int main()
{
scanf("%d",&t);
int res=1;
while(t--)
{
memset(b,0,sizeof(b));//初始化
memset(a,0,sizeof(a));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(i,a[i]);//建树
}
printf("Case %d:\n",res++);
while(scanf("%s",c),strcmp(c,"End"))
{
int x,y;
scanf("%d%d",&x,&y);
if(c[0]=='A')//增
add(x,y);
else if(c[0]=='S')//减
add(x,-y);
else if(c[0]=='Q')//查询
printf("%d\n",sum(y)-sum(x-1));
}
}
return 0;
}