題目鏈接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=66989#problem/A
題意:動態修改某個點的值,然後動態詢問區間和。
標準的線段樹點修改問題,以前做過,第一次看着別人的代碼用線段樹水過了,後來還用樹狀數組做過(現在不記得樹狀數組了。。。。),現在再次用線段樹寫,當然這次是獨立寫的。題意本身不難,但是有一個值的注意,本題輸入與輸出量比較大,得用scanf與printf,否則果斷TLE。
代碼:
#include<iostream>
#include<cstdio>
#define maxn 50010
using namespace std;
struct node{
int l,r,w;
}T[maxn*3];
int N,A[maxn];//A數組要不要都行,初始時,每輸入一個值調用一次add
char s[10];
int build(int L,int R,int o){
T[o].l=L;T[o].r=R;
if(L==R) return T[o].w=A[L];
return T[o].w=build(L,(L+R)/2,o*2)+build((L+R)/2+1,R,o*2+1);
}
void add(int L,int R,int val,int o){
if(T[o].l>=L && T[o].r<=R){
T[o].w+=val;return;
}
if(T[o].l==T[o].r) return;
T[o].w+=val;
int tl=o*2,tr;tr=tl+1;
if(L>=T[tr].l) add(L,R,val,tr);
else if(R<=T[tl].r) add(L,R,val,tl);
else{
add(L,T[tl].r,val,tl);
add(T[tr].l,R,val,tr);
}
}
int query(int L,int R,int o){
if(T[o].l>=L && T[o].r<=R) return T[o].w;
if(T[o].l==T[o].r) return 0;
int tl=o*2,tr;tr=tl+1;
if(L>=T[tr].l) return query(L,R,tr);
if(R<=T[tl].r) return query(L,R,tl);
return query(L,T[tl].r,tl)+query(T[tr].l,R,tr);
}
int main(){
//freopen("D:\\in.txt","r",stdin);
int T;cin>>T;
for(int kase=1;kase<=T;kase++){
cin>>N;
for(int i=0;i<N;i++)
scanf("%d",A+i+1);
build(0,N,1);
printf("Case %d:\n",kase);
while(scanf("%s",s) && s[0]!='E'){
int a,b;
scanf("%d %d",&a,&b);
if(s[0]=='Q') printf("%d\n",query(a,b,1));
else if(s[0]=='A') add(a,a,b,1);
else add(a,a,0-b,1);//減法發也可以是加法
}
}
return 0;
}