单点更新 区间查询
坑点:cin cout 一直超时 改成 scanf 和printf 就过了
/*输入 t样例 N(N<=50000) 第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 表示结束,这条命令在每组数据最后出现; 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 */ #include <string.h> #include <stdio.h> using namespace std; int n,t[50005]; int lowbit(int x) { return x&(-x); } void update(int x,int val)//单点更新 { while(x<=n){ t[x]+=val; x+=lowbit(x);//由叶子节点向上更新树状数组C,从左往右更新 } } int ask(int x)//求区间[1,i]内所有元素的和 即求前缀和 { int ans=0; while(x>0){ ans+=t[x];//从右往左累加求和 x-=lowbit(x); } return ans; } int main() { int tt,cnt=0,b,c,i,a; char s[10]; scanf("%d",&tt); while(tt--) { scanf("%d",&n); memset(t,0,sizeof(t)); for(i=1;i<=n;i++) { scanf("%d",&a); update(i,a); } printf("Case %d:\n",++cnt); while(scanf("%s",s)) { if(s[0]=='E') break; scanf("%d%d",&c,&b); if(s[0]=='S') update(c,-b); if(s[0]=='A') update(c,b); if(s[0]=='Q') { printf("%d\n",ask(b)-ask(c-1)); } } } return 0; }