hdu 1166 敌兵布阵(基本操作)
有三种操作:询问区间总和,增加某个兵营的兵的数目,减少某个兵营的兵的数目。实际上也只有两个。
在更新的时候,每到一个区间就把当前区间的sum增加对应的数目,到达叶子结点是返回。这样就可以不会回溯去更新父亲结点的值。查询的时候,如果区间完全匹配,直接返回区间的sum值,否则向下寻找,直到完全匹配,然后返回它们的和就可以。这时候,结果里保存的边界是它们真正的边界。
/*更新了代码风格后*/
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define MID(a,b) (a+((b-a)>>1)) const int N=50005; struct node { int lft,rht; int sum; int mid(){return MID(lft,rht);} }; int y[N],n; struct Segtree { node tree[N*4]; void build(int lft,int rht,int ind) { tree[ind].lft=lft; tree[ind].rht=rht; tree[ind].sum=0; if(lft==rht) tree[ind].sum=y[lft]; else { int mid=tree[ind].mid(); build(lft,mid,LL(ind)); build(mid+1,rht,RR(ind)); tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum; } } void updata(int pos,int ind,int valu) { if(tree[ind].lft==tree[ind].rht) tree[ind].sum+=valu; else { int mid=tree[ind].mid(); if(pos<=mid) updata(pos,LL(ind),valu); else updata(pos,RR(ind),valu); tree[ind].sum=tree[LL(ind)].sum+tree[RR(ind)].sum; } } int query(int st,int ed,int ind) { int lft=tree[ind].lft,rht=tree[ind].rht; if(st<=lft&&rht<=ed) return tree[ind].sum; else { int mid=tree[ind].mid(); int sum1=0,sum2=0; if(st<=mid) sum1=query(st,ed,LL(ind)); if(ed>mid) sum2=query(st,ed,RR(ind)); return sum1+sum2; } } }seg; int main() { int t,t_cnt=0; scanf("%d",&t); while(t--) { int a,b; char str[10]; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&y[i]); seg.build(1,n,1); printf("Case %d:\n",++t_cnt); while(1) { scanf("%s",str); if(strcmp(str,"End")==0) break; scanf("%d%d",&a,&b); if(strcmp(str,"Add")==0) seg.updata(a,1,b); else if(strcmp(str,"Sub")==0) seg.updata(a,1,-b); else printf("%d\n",seg.query(a,b,1)); } } return 0; }
/*代码风格更新前*/
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int N=1000005; int a[N]; struct node { int left,right,sum; int mid(){ return left+(right-left)/2;} }; struct Segtree { node tree[N*4]; void build(int left,int right,int p) { tree[p].left=left; tree[p].right=right; tree[p].sum=0; if(left<right) { int mid=tree[p].mid(); build(left,mid,p*2); build(mid+1,right,p*2+1); } else if(left==right) { tree[p].sum=a[left]; return; } tree[p].sum=tree[p*2].sum+tree[p*2+1].sum; } void updata(int pos,int p,int data) { tree[p].sum+=data; int mid=tree[p].mid(); if(tree[p].left==pos&&tree[p].right==pos) return; else if(pos<=mid) updata(pos,p*2,data); else if(pos>mid) updata(pos,p*2+1,data); } int query(int be,int end,int p) { int left=tree[p].left; int right=tree[p].right; if(be<=left&&right<=end) { return tree[p].sum; } else { int sum1=0,sum2=0; int mid=tree[p].mid(); if(be<=mid) sum1=query(be,end,p*2); if(end>mid) sum2=query(be,end,p*2+1); return sum1+sum2; } } }seg; int main() { int t,t_cnt=0; scanf("%d",&t); while(t--) { int n,x,y; char temp[10]; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); printf("Case %d:\n",++t_cnt); seg.build(1,n,1); while(scanf("%s",temp)!=EOF) { if(strcmp(temp,"End")==0) break; else if(strcmp(temp,"Add")==0) { scanf("%d%d",&x,&y); seg.updata(x,1,y); } else if(strcmp(temp,"Sub")==0) { scanf("%d%d",&x,&y); seg.updata(x,1,-y); } else if(strcmp(temp,"Query")==0) { scanf("%d%d",&x,&y); printf("%d\n",seg.query(x,y,1)); } } } return 0; }