题目:hdoj1166
分析:题意很清晰,就是让你给某个点又增加或者减少x个,然后求某一段有多少个,我是用一个father数组保存叶子节点的编号,然后直接从当前节点开始,更轻到root就ok。
查询的话,从根节点开始,看在左子区间还是右子区间,直接查询到某一段全部在要查询的区间内,求和就ok,很简单。
代码:
#include#include #include using namespace std ; const int N = 55000 ; struct Node { int l ,r ; int sum ; }; Node tree [4 *N ]; int a [N ]; int fa [N ]; void build (int l ,int r ,int v ) { tree [v ].l =l ; tree [v ].r =r ; if(l ==r ) { fa [l ]=v ; tree [v ].sum =a [l ]; return ; } int mid =(l +r )>>1 ; build (l ,mid ,v *2 ); build (mid +1 ,r ,v *2 +1 ); tree [v ].sum =tree [v +v ].sum +tree [v +v +1 ].sum ; } void update (int t ,int p ) { tree [t ].sum +=p ; if(t ==1 ) return ; update (t /2 ,p ); } int queue (int a ,int b ,int v ) { if(tree [v ].l ==a &&tree [v ].r ==b ) { return tree [v ].sum ; } int mid =(tree [v ].l +tree [v ].r )>>1 ; if(b <=mid ) return queue (a ,b ,v +v ); else if(a >mid ) return queue (a ,b ,v +v +1 ); else return queue (a ,mid ,v *2 )+queue (mid +1 ,b ,v *2 +1 ); } int main() { int T ,n ; char str [10 ]; int x ,y ; scanf ("%d" ,&T ); for(int cas =1 ; cas <=T ; cas ++) { scanf ("%d" ,&n ); for(int i =1 ; i <=n ; i ++) scanf ("%d" ,&a [i ]); build (1 ,N ,1 ); printf ("Case %d:\n" ,cas ); while(scanf ("%s" ,str )>0 ) { if(str [0 ]=='A' ) { scanf ("%d %d" ,&x ,&y ); update (fa [x ],y ); } else if(str [0 ]=='S' ) { scanf ("%d %d" ,&x ,&y ); update (fa [x ],-y ); } else if(str [0 ]=='Q' ) { scanf ("%d %d" ,&x ,&y ); int ans =queue (x ,y ,1 ); printf ("%d\n" ,ans ); } else { break; } } } }