hdu1166:http://acm.hdu.edu.cn/showproblem.php?pid=1166
题意:n个阵营一字排开,每个初始有a[i]个人。现有两种操作:Q a b 查询[a,b]之间总人数并输出A/S a b 在a号位添加/删除b个人
题解:用线段树维护,就是单点更新,区间查询。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 using namespace std; 6 int n,a,b; 7 struct Node{ 8 int left;//左二子 9 int right;//右儿子 10 int sum;//一顶点为子树的和 11 }node1[50005*4];//这里一定要注意,是4倍的点,不然会越界,自己犯过错 12 void build(int l,int r,int idx){//建树 13 node1[idx].left=l; 14 node1[idx].right=r;//注意这里,第一次,把这里弄丢了 15 if(l==r){ 16 scanf("%d",&node1[idx].sum);//到底就读取数据 17 return; 18 } 19 int midx=(l+r)>>1; 20 build(l,midx,idx<<1);//向下建立子树 21 build(midx+1,r,(idx<<1)+1); 22 node1[idx].sum=node1[idx<<1].sum+node1[(idx<<1)+1].sum;//建完子树,向上更新父亲节点的和 23 } 24 int query(int s,int t,int idx){//区间查询 25 if(s==node1[idx].left && t==node1[idx].right){ 26 return node1[idx].sum; 27 } 28 int midx=(node1[idx].left+node1[idx].right)/2;//这里第一次忘记了/2,找了几个小时 29 if(midx>=t) return query(s,t,idx*2);//在左二子 30 else if(midx<s)return query(s,t,idx*2+1);//在右儿子 31 else { 32 return (query(s,midx,idx*2)+query(midx+1,t,idx*2+1));//在中间 33 } 34 } 35 void update(int p,int add,int l,int r,int idx ){//单点更新 36 if(node1[idx].left==node1[idx].right){ 37 node1[idx].sum+=add; 38 return; 39 } 40 int midx=(r+l)/2; 41 if(p<=midx) 42 update(p,add,l,midx,idx*2); 43 else 44 update(p,add,midx+1,r,idx*2+1); 45 node1[idx].sum=node1[idx*2].sum+node1[idx*2+1].sum; //向上更新,不是+=,是= 46 } 47 int main(){ 48 int cas;char ss[8]; 49 scanf("%d",&cas); 50 int t=1; 51 while(cas--){ 52 printf("Case %d: ",t++); 53 scanf("%d",&n); 54 build(1,n,1); 55 while(~scanf("%s",ss)){ 56 if(ss[0]=='E')break; 57 if(ss[0]=='Q'){ 58 scanf("%d%d",&a,&b); 59 printf("%d ",query(a,b,1)); 60 } 61 else if(ss[0]=='A'){ 62 scanf("%d%d",&a,&b); 63 update(a,b,1,n,1); 64 } 65 else{ 66 scanf("%d%d",&a,&b); 67 update(a,-b,1,n,1); 68 } 69 } 70 } 71 }