这是一道最简单的线段树的更新节点与区间查询。
当然practic makes perfect~ 现在我已经能够比较熟练地打出来了。
但是还有一些细节要注意就是对于父节点的更新。
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> using namespace std; #define maxn 55555 char a[55]; struct node{ int l,r,sum; int add; }tree[maxn*4]; int ans=0; void pushup(int v){ int temp=v*2; tree[v].sum=tree[temp].sum+tree[temp+1].sum; } void pushdown(int v){ int temp=v*2; tree[temp].add+=tree[v].add; tree[temp+1].add+=tree[v].add; tree[temp].sum+=tree[v].add*(tree[temp].r-tree[temp].l+1); tree[temp+1].sum+=tree[v].add*(tree[temp+1].r-tree[temp+1].l+1); tree[v].add=0; } void build(int l,int r,int v){ tree[v].l=l; tree[v].r=r; tree[v].add=0; if(l==r){ scanf("%d",&tree[v].sum); return; } int temp=v*2; int mid=(tree[v].l+tree[v].r)/2; build(l,mid,temp); build(mid+1,r,temp+1); pushup(v); } void update(int pos,int v,int x){ if(pos==tree[v].l&&tree[v].r==pos){ tree[v].add+=x; tree[v].sum+=x*(tree[v].r-tree[v].l+1); return ; } if(tree[v].add) pushdown(v); int mid=(tree[v].l+tree[v].r)/2; int temp=v*2; if(pos<=mid) update(pos,temp,x); else update(pos,temp+1,x); pushup(v); //!!! } void query(int l,int r,int v){ if(r<tree[v].l||tree[v].r<l) return; if(l<=tree[v].l&&tree[v].r<=r){ ans+=tree[v].sum; return; } if(tree[v].add) pushdown(v); int mid=(tree[v].l+tree[v].r)/2; int temp=v*2; if(r<=mid) query(l,r,temp); else if(mid<l) query(l,r,temp+1); else{ query(l,mid,temp); query(mid+1,r,temp+1); } } int main(){ int T,n; int j=1; scanf("%d",&T); while(T--){ scanf("%d",&n); ans=0; bool ff=false; build(1,n,1); #if 1 while(1){ scanf("%s",a); if(strcmp(a,"End")==0) break; if(strcmp(a,"Add")==0){ int r,s; scanf("%d%d",&r,&s); update(r,1,s); } if(strcmp(a,"Sub")==0){ int r,s; scanf("%d%d",&r,&s); update(r,1,-s); } if(strcmp(a,"Query")==0){ ans=0; int r,s; scanf("%d%d",&r,&s); query(r,s,1); if(!ff) printf("Case %d:\n",j++),ff=true; printf("%d\n",ans); } } #endif } }
原文地址:http://blog.csdn.net/acmer_hades/article/details/46489297