【Problem】http://acm.hdu.edu.cn/showproblem.php?pid=1166php
給定一個數組a[]和一系列的操做,應答每一個詢問。ios
操做:Add i x:a[i]+=x Sub i x:a[i]-=x Query l r:詢問Σ(a[l..r])數組
【Analysis】ui
對於Sub i x操做,徹底能夠用Add i -x來代替。spa
標準的線段樹,比較簡單類型的。具體的能夠去看wiki。code
【Code】get
// Task: 1166 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> using namespace std; #define nil NULL class SegmentTree { public: int x; // 節點值 int l,r; // 區間左右標記 SegmentTree*left,*right; // 左右子樹 SegmentTree (int L=0,int R=0) { l=L,r=R; x=0; left=right=nil; } }*root; SegmentTree*Build(int a[],int L,int R) { if (L>R) return nil; else { SegmentTree*ret=new SegmentTree(L,R); if (L==R) ret->x=a[L]; else { int K=(L+R)>>1; if ((ret->left=Build(a,L,K))!=nil) ret->x+=ret->left->x; if ((ret->right=Build(a,K+1,R))!=nil) ret->x+=ret->right->x; } // cout << L << " " << R << " " << ret->x << endl; return ret; } } void Add(int i,int x) { SegmentTree*p=root; while (p!=nil) { p->x+=x; int k=(p->l+p->r)>>1; if (i<=k) p=p->left; else p=p->right; } } int Query(int l,int r,SegmentTree*p=root) { if (p==nil||l>r) return 0; else { int ret=0; if (p->l==l&&p->r==r) return p->x; // 完美包含 int k=(p->l+p->r)>>1; if (r<=k) return Query(l,r,p->left); // 全都在左子樹 if (l>k) return Query(l,r,p->right); // 全都在右子樹 if (l<=k) ret+=Query(l,k,p->left); // 交叉包含左子樹部分 if (r>k) ret+=Query(k+1,r,p->right); // 交叉包含右子樹部分 // printf("%d(%d)-%d(%d) %d\n",l,p->l,r,p->r,ret); return ret; } } const int N = 50000; int n; int a[N+1]; char cmd[10]; int main() { int T; scanf("%d",&T); for (int dex=1;dex<=T;dex++) { printf("Case %d:\n",dex); scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",a+i); root=Build(a,1,n); scanf("%s",cmd); while (cmd[0]!='E') { int l,r; scanf("%d%d",&l,&r); switch(cmd[0]) { case 'A':Add(l,r);break; case 'S':Add(l,-r);break; case 'Q':printf("%d\n",Query(l,r));break; } scanf("%s",cmd); } } return 0; }