#include<iostream>#include<string>using namespace std;struct BTs{ int e; int r; int l;};const int M = 50002*10;BTs a[M];int b[50010];inline void init(int k,int h,int x) //k 为左边界 h为右边界 x 数组下标{ a[x].r = h; //从叶子节点自下而上建树,叶子节点即是最小不可分的区间 a[x].l = k; if(k == h) { a[x].e = b[k]; return ; } else { init(k,(k+h)/2,2*x); init((k+h)/2+1,h,2*x+1); a[x].e = a[2*x].e + a[2*x+1].e; }}inline void change_plus(int index,int addend,int k) //k数组下标{ if(a[k].l <= index&&a[k].r >=index) //更新了所有覆盖的区域 { a[k].e += addend; change_plus(index,addend,k*2); change_plus(index,addend,k*2+1); } else return ;}inline void change_sub(int index,int m,int k){ if(a[k].l <= index&&a[k].r >=index) { a[k].e -= m; change_sub(index,m,k*2); change_sub(index,m,k*2+1); } else return ;}int count;inline void query(int L,int R,int k){ if(L == a[k].l&&R == a[k].r) //找到了相应的区间,计数; { count += a[k].e; // cout<<"\""<<k<<"\""<<count<<endl; return; } else if(L <= (a[k].l + a[k].r)/2&&R >= (a[k].r + a[k].l)/2+1) //在搜索区间值的时候把区间边界和对应区间边界的数组坐标弄混了 { query(L,(a[k].l+a[k].r)/2,k*2); query((a[k].l+a[k].r)/2+1,R,k*2+1); } else if(R <= (a[k].r+a[k].l)/2) query(L,R,k*2); else if(L >= (a[k].l+a[k].r)/2+1) query(L,R,k*2+1);}int main(){ int T; cin>>T; int rc = T; while(T) { cout<<"Case "<<rc-T+1<<":"<<endl; int c; cin>>c; for(int i = 1; i <= c; i++) cin>>b[i]; init(1,c,1);//for(int i = 1; i < 4*c; i++) //cout<<"\""<<i<<"\""<<a[i].e<<endl; while(1) { string s; int i,j; cin>>s; if(s == "Sub") { cin>>i>>j; change_sub(i,j,1); } if(s == "Add") { cin>>i>>j; change_plus(i,j,1); } if(s == "Query") { cin>>i>>j; count = 0; query(i,j,1); //cout<<query(i,j,1)<<endl; cout<<count<<endl; } if(s == "End") { break; } } T--; } return 0;}
这一题我没有套模板去做,只是了解了线段树的概念之后,全部自己琢磨著敲的。主要是想看看自己的思路哪里有差距,也正好让自己多犯点错。