线段树模板
2017-04-07 19:16
197 查看
点更新与区间查询
区间更新模板(用到了懒惰标记,区间更新是线段树的核心,只能最大最小值的线段树)
#include<iostream> #include<cstdio> #include<algorithm> usingnamespacestd; constintmaxn=200010; structnode { intmark; intmax; }stu[4*maxn]; voidbuild(intl,intr,inti)//i为结构体数组的下标 { stu[i].max=0;//给每个节点赋初值 if(l==r){ scanf("%d",&stu[i].mark); stu[i].max=stu[i].mark;//当最后线段等于点的时候赋初值。最底层!!,递归结束,一层一层的结束 return; } intmid=(l+r)/2; build(l,mid,i<<1);//zuo build(mid+1,r,(i<<1)+1);//you stu[i].max=max(stu[i<<1].max,stu[(i<<1)+1].max);//递归,顾名思义就是自下而上,不断地从下往上更新答案,最后退出的肯定是根节点i=1 } voidupdate(intl,intr,inti,intx,inty)//i数组下标,x待查数据下标,y待查数据的变化量 { if(l==r){//说明不断二分找到了x,就是l==r==x; stu[i].mark=y; stu[i].max=stu[i].mark; return; } intmid=(l+r)/2;//找到中间 if(x<=mid) update(l,mid,i<<1,x,y); else update(mid+1,r,(i<<1)+1,x,y); stu[i].max=max(stu[i<<1].max,stu[(i<<1)+1].max); } intquerymax(intl,intr,inti,intx,inty)//区间查询 { if(x<=l&&y>=r)returnstu[i].max;//如果覆盖就选择区间内的最大值 intmid=(l+r)/2;//这个地方要注意,要把x,y分开与mid比较,这样就可以通过不断地递归,将左右两端都求解出来 intMax=0; if(x<=mid)//如果x在左,这是一种特殊情况,y不能确定,但是x不在左,那x肯定在右,y也必定在右 Max=max(Max,querymax(l,mid,i<<1,x,y)); if(y>mid) Max=max(Max,querymax(mid+1,r,(i<<1)+1,x,y)); returnMax; }
区间更新模板(用到了懒惰标记,区间更新是线段树的核心,只能最大最小值的线段树)
#include<iostream> #include<cstdio> usingnamespacestd; constintmaxn=10000; structnode { intval; intadd;//延迟标记 }segTree[4*maxn]; voidpushdown(inti) { if(segTree[i].add!=0){ //先向下传递标记 segTree[i<<1].add+=segTree[i].add;//设置左右孩子为标志域,孩子节点可能被多次延迟标记又没有向下传递 segTree[(i<<1)+1].add+=segTree[i].add; //将标记赋给子节点 segTree[i<<1].val+=segTree[i].add; segTree[(i<<1)+1].val+=segTree[i].add; //将标记清零 segTree[i].add=0; } } voidbuild(inti,intl,intr) { segTree[i].add=0;//设置延迟标记域 if(l==r){ scanf("%d",&segTree[i].val); return; } intmid=(l+r)>>1; build(i<<1,l,mid); build((i<<1)+1,mid+1,r); segTree[i].val=max(segTree[i<<1].val,segTree[(i<<1)+1].val); } //点更新 voidupdate1(inti,intl,intr,intx,inty)//x是被更新的位置,y是增量,点更新 { if(l==r){ segTree[i].val+=y; return; } intmid=(l+r)>>1; if(x<=mid) update1(i<<1,l,mid,x,y); else update1((i<<1)+1,mid+1,r,x,y); segTree[i].val=max(segTree[i<<1].val,segTree[(i<<1)+1].val); } //区间更新 voidupdate(inti,intl,intr,intx,inty,intaddval)//i下标,lr左右,xy所选区间,addval增量 { if(y<l||x>r)return; if(x<=l&&y>=r){ segTree[i].add+=addval;//最低端加标记 segTree[i].val+=addval;//赋值标记, return; } pushdown(i);//自下而上更新区间上的懒惰标记 intmid=(l+r)/2; update(i<<1,l,mid,x,y,addval); update((i<<1)+1,mid+1,r,x,y,addval); segTree[i].val=max(segTree[i<<1].val,segTree[(i<<1)+1].val);//不断的判断更新标记。 } intquerymax(inti,intl,intr,intx,inty)//被查询的区间 { if(x<=l&&y>=r)returnsegTree[i].val; intmid=(l+r)>>1; pushdown(i);//延时标记域向下传递 intMax=0; if(x<=mid) Max=max(Max,querymax(i<<1,l,mid,x,y)); if(y>mid) Max=max(Max,querymax((i<<1)+1,mid+1,r,x,y)); returnMax; } intmain() { }
线段树模板终极版,区间求和,延迟标记
#include<iostream>
#include<cstdio>
usingnamespacestd;
constintmaxn=100000+10;
structnode{
intleft,right;
longlonglazy,sum;
voidupdate(longlongx){//延迟标记
sum+=(right-left+1)*x;
lazy+=x;
}
}tree[4*maxn];
inta[maxn];
inti;
voidpushdown(intid)
{
intl=tree[id].lazy;
if(l){
tree[id<<1].update(l);
tree[id<<1|1].update(l);
tree[id].lazy=0;
}
}
voidpushup(intid)
{
tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;
}
voidbuild(intid,intl,intr)
{
tree[id].left=l;
tree[id].right=r;
tree[id].sum=tree[id].lazy=0;
if(l==r){
tree[id].sum=a[l];//这个地方一般是scanf!!!!!!!
return;
}
intmid=(l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
pushup(id);//更新
}
voidupdate(intid,intl,intr,intval)//区间更新
{
intL=tree[id].left,R=tree[id].right;
if(l<=L&&R<=r){
tree[id].update(val);
return;
}
else{
pushdown(id);
intmid=(L+R)>>1;
if(l<=mid)update(id<<1,l,r,val);
if(r>mid)update(id<<1|1,l,r,val);
pushup(id);
}
}
longlongquery(intid,intl,intr)//区间查询
{
intL=tree[id].left,R=tree[id].right;
if(l<=L&&R<=r)
returntree[id].sum;
else{
pushdown(id);
intmid=(L+R)>>1;
intres=0;
if(l<=mid)res+=query(id<<1,l,r);
if(r>mid)res+=query(id<<1|1,l,r);
pushup(id);
returnres;
}
}
相关文章推荐
- [poj3468]线段树模板
- 线段树模板
- 可持久化线段树 (模板)
- 线段树简单入门模板--单点更新
- 【luogu3372】模板 线段树1
- hdu1754—I Hate It(线段树模板)
- 比较快也比较漂亮的熟练剖分模板(BZOJ 1036:树剖+线段树 BZOJ 1103:树剖+树状数组)
- 线段树模板(区间更新)
- 线段树模板
- 洛谷 P3372 【模板】线段树 1
- 线段树模板及专题合集-----不断更新中
- 线段树模板 (poj 3468)延迟标记
- 【模板】线段树单点修改
- 【模板】线段树 洛谷 3372 线段树
- 线段树模板(NOTONLYSUCCESS神牛)
- 线段树(简单模板)
- 线段树模板
- 线段树模板
- 线段树实现RMQ问题(线段树模板的基本应用)
- Luck and Love(二维线段树单点更新+区间查询+模板)