很基础,每个节点记录该线段覆盖的点的人数的总和,add(k)的时候,叶子节点加k,然后更新父亲节点,sub看做add(-k),query 则查找满足条件区间的值即可。
View Code
Problem : 1166 ( 敌兵布阵 ) Judge Status : Accepted
RunId : 11285750 Language : G++ Author : lihaozhuzhuxia Code Render Status : Rendered By HDOJ G++ Code Render Version 0.01 Beta #include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; struct p { int l; int r; int sum; } tree[555555]; int value[55555];//存放节点初始值 void construct(int n,int l,int r)//从n节点开始建区间为l到r的树 { int i,j,k,m; if(l==r) { tree[n].l=tree[n].r=l; tree[n].sum=value[l]; return; } int mid=(l+r)/2; tree[n].l=l; tree[n].r=r; construct(2*n,l,mid); construct(2*n+1,mid+1,r); tree[n].sum=tree[n*2].sum+tree[n*2+1].sum; } void add(int l,int r,int n,int k) { int i,j,m; if(tree[n].l==l&&tree[n].r==r)//一直递归查找,直到找到叶子节点 { tree[n].sum+=k; //叶子节点+k; return ; } int mid=(tree[n].l+tree[n].r)/2; if(l<=mid) { add(l,r,n*2,k); } else { add(l,r,n*2+1,k); } tree[n].sum=tree[n*2+1].sum+tree[n*2].sum;//递归返回时,更新父亲节点的信息; } int query(int l,int r,int n) { int i,j,k,m,sum=0; if(tree[n].l==l&&tree[n].r==r) { return tree[n].sum; } int mid=(tree[n].l+tree[n].r)/2; if(r<=mid) { sum+=query(l,r,n*2); } else if(l>mid) { sum+=query(l,r,n*2+1); } else { sum+=query(l,mid,n*2); sum+=query(mid+1,r,n*2+1); } return sum; } int main() { int i,j,k,l,m,r,n; int t; scanf("%d",&t); char s[111]; int o=0; while(t--) { o++; scanf("%d",&n); for(i=1; i<=n; i++) { scanf("%d",&value[i]); } construct(1,1,n); printf("Case %d:\n",o); while(scanf("%s",s)==1) { if(s[0]=='E') break; if(s[0]=='Q') { scanf("%d%d",&l,&r); printf("%d\n",query(l,r,1)); } if(s[0]=='A') { scanf("%d%d",&l,&k); add(l,l,1,k); } if(s[0]=='S') { scanf("%d%d",&l,&k); add(l,l,1,-k); } } } |