线段树
c.单点更新
/* 线段树 单点更新 */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; #define L(root) ((root)<<1) #define R(root) (((root)<<1)|1) const int MAXN=1024;// int numbers[MAXN];//初始值 struct node{ int left,right;// int sum; int mid(){ return left+((right-left)>>1); } }tree[MAXN*4];//4倍空间 void pushUp(int root){ tree[root].sum=tree[L(root)].sum+tree[R(root)].sum; } void build(int root,int left,int right){ tree[root].left=left; tree[root].right=right; if(left==right){ tree[root].sum=numbers[left]; return; } int mid=tree[root].mid(); build(L(root),left,mid); build(R(root),mid+1,right); pushUp(root); } int query(int root,int left,int right){ if(tree[root].left==left&&tree[root].right==right){ return tree[root].sum; } int mid=tree[root].mid(); if(right<=mid){ return query(L(root),left,right); } else if(left>mid){ return query(R(root),left,right); } else{ return query(L(root),left,mid)+query(R(root),mid+1,right); } } void update(int root,int pos,int add){ if(tree[root].left==tree[root].right){ tree[root].sum+=add; return; } int mid=tree[root].mid(); if(pos<=mid){ update(L(root),pos,add); } else{ update(R(root),pos,add); } pushUp(root); } int main(){ memset(numbers,0,sizeof(numbers)); int i; for(i=1;i<MAXN;++i){ numbers[i]=i; } build(1,1,10); cout<<query(1,2,3)<<endl; update(1,2,100); cout<<query(1,2,3)<<endl; return 0; }
c'.单点更新,写法与c稍有差异,要理解
/* 线段树 单点更新 */ #include<iostream> #include<stdio.h> using namespace std; #define MAXN 50005 int ans; struct node{ int left,right,sum; int mid(){ return (left+right)>>1; } }tree[MAXN*4];//注意范围,4倍空间 void btree(int left,int right,int rt){//建树 tree[rt].left=left; tree[rt].right=right; if(left==right){ scanf("%d",&tree[rt].sum); return; } int mid=tree[rt].mid(); btree(left,mid,rt<<1); btree(mid+1,right,rt<<1|1); tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;//区间里的点数=左区间+右区间 } void query(int left,int right,int rt,int L,int R){//询问求和 if(L<=left&&right<=R){ ans+=tree[rt].sum; return; } int mid=tree[rt].mid(); if(R<=mid)query(left,mid,rt<<1,L,R);//区间在左子树 else if(L>mid)query(mid+1,right,rt<<1|1,L,R);//区间在右子树 else{ query(left,mid,rt<<1,L,R); query(mid+1,right,rt<<1|1,L,R); } } void update(int left,int right,int rt,int pos,int add){//单点更新函数 if(left==right){ tree[rt].sum+=add; return; } int mid=tree[rt].mid(); if(pos<=mid)update(left,mid,rt<<1,pos,add);//点在左子树 else update(mid+1,right,rt<<1|1,pos,add);//点在右子树 tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;//区间和更新 } int main(){ int t,n,a,b,i; char str[10]; scanf("%d",&t); for(i=1;i<=t;++i){ printf("Case %d:\n",i); scanf("%d",&n); btree(1,n,1); while(~scanf("%s",str)&&str[0]!='E'){ scanf("%d%d",&a,&b); if(str[0]=='A')update(1,n,1,a,b); else if(str[0]=='S')update(1,n,1,a,-b); else{ ans=0; query(1,n,1,a,b); printf("%d\n",ans); } } } return 0; }
c2.区间更新
/* 线段树 区间更新 */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; #define L(root) ((root)<<1) #define R(root) (((root)<<1)|1) const int MAXN=1024;// int numbers[MAXN];//初始值 struct node{ int left,right;// int sum; int delta; int mid(){ return left+((right-left)>>1); } }tree[MAXN*4];//4倍空间 void pushUp(int root){ tree[root].sum=tree[L(root)].sum+tree[R(root)].sum; } void pushDown(int root){ if(tree[root].delta){ tree[L(root)].delta+=tree[root].delta; tree[R(root)].delta+=tree[root].delta; tree[L(root)].sum+=tree[root].delta*(tree[L(root)].right-tree[L(root)].left+1); tree[R(root)].sum+=tree[root].delta*(tree[R(root)].right-tree[R(root)].left+1); tree[root].delta=0; } } void build(int root,int left,int right){ tree[root].left=left; tree[root].right=right; tree[root].delta=0;//不要忘了清空这个 if(left==right){ tree[root].sum=numbers[left]; return; } int mid=tree[root].mid(); build(L(root),left,mid); build(R(root),mid+1,right); pushUp(root); } int query(int root,int left,int right){ if(tree[root].left==left&&tree[root].right==right){ return tree[root].sum; } pushDown(root); int mid=tree[root].mid(); if(right<=mid){ return query(L(root),left,right); } else if(left>mid){ return query(R(root),left,right); } else{ return query(L(root),left,mid)+query(R(root),mid+1,right); } } void update(int root,int left,int right,int add){ if(tree[root].left==left&&tree[root].right==right){ tree[root].delta+=add; tree[root].sum+=add*(right-left+1); return; } pushDown(root); int mid=tree[root].mid(); if(right<=mid){ update(L(root),left,right,add); } else if(left>mid){ update(R(root),left,right,add); } else{ update(L(root),left,mid,add); update(R(root),mid+1,right,add); } pushUp(root); } int main(){ memset(numbers,0,sizeof(numbers)); int i; for(i=1;i<MAXN;++i){ numbers[i]=i; } build(1,1,10); cout<<query(1,2,3)<<endl; update(1,2,3,100); cout<<query(1,2,3)<<endl; return 0; }
ps:node节点里面的left和right信息也可以不用保存,在调用函数的时候传下去也可以。
模板:http://blog.csdn.net/wjw0130/article/details/38498481