这是一道最简单的线段树的更新节点与区间查询。
当然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
}
}