题目描述:见杭电OJ http://acm.hdu.edu.cn/showproblem.php?pid=1166
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
解题思路:利用线段树(构建、区间更新、区间查询)
代码如下:
//线段树 敌兵布阵 //http://acm.hdu.edu.cn/showproblem.php?pid=1166 #include"iostream" #include"cstdio" #include"cstring" using namespace std; struct _tree{ int l,r,sum; int getmid(){ return ((l + r)/2); } }tree[50005*4]; //构建线段树 void BulidTree(int l,int r,int pos) { tree[pos].l = l; tree[pos].r = r; tree[pos].sum=0; if(l == r) return; int mid = tree[pos].getmid() ; BulidTree(l,mid,pos*2); BulidTree(mid + 1,r,pos*2 + 1); } //区间更新(包括增加和减少) void UpdataTree(int count,int x,int pos) { tree[pos].sum += count; //printf("pos= %d[%d,%d] %d\n",pos,tree[pos].l,tree[pos].r,tree[pos].sum); if(tree[pos].l == tree[pos].r) return ; int mid = tree[pos].getmid() ; if(x <= mid) UpdataTree(count,x,2*pos); else UpdataTree(count,x,2*pos + 1); } //区间查询 int Query(int x,int y,int pos) { if(tree[pos].l == x && tree[pos].r == y) return tree[pos].sum; int mid = tree[pos].getmid() ; if(y <= mid) return Query(x,y,pos*2); else if(x >mid ) return Query(x,y,pos*2+1); else return Query(x,mid,pos*2) + Query(mid + 1,y,pos*2+1); } //主函数 int main() { int T; cin>>T; for(int cas = 1;cas <= T;cas++){ printf("Case %d:\n",cas); int n; scanf("%d",&n); BulidTree(1,n,1);//生成线段树 int temp; for(int i = 1;i <= n;i++){ scanf("%d",&temp); UpdataTree(temp,i,1); } char op[8]; while(cin>>op){ if(!strcmp(op,"Query")){ int x,y; scanf("%d%d",&x,&y); printf("%d\n",Query(x,y,1)); } if(!strcmp(op,"Add")){ int x,t; scanf("%d%d",&x,&t); UpdataTree(t,x,1); } if(!strcmp(op,"Sub")){ int x,t; scanf("%d%d",&x,&t); UpdataTree(-t,x,1); } if(!strcmp(op,"End")) break; } } return 0; }