码迷,mamicode.com
首页 > 其他好文 > 详细

线段树

时间:2018-02-10 19:27:50      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:树节点   节点   标记   int   清空   思想   区间修改   信息   最大   

线段树


O(log(n))个区间覆盖L~R信息
每层最多选两个区间

区间最大值

int n;
int a[];
int mx[];
// 当前节点编号,当前表示的区间范围
void build(int o,int l,int r){
if(l==r){
mx[o] = a[l];
}else{
int mid=(l+r)/2;
build(o*2,l,mid);
build(o*2+1,mid+1,r);
mx[o]=max(mx[o*2],mx[o*2+1]);
}
}
build(1,1,n)

// o结点编号,l,r线段树的区间,L,R查询的区间
int ask(int o,int l,int r,int L,int R){
if(l==L&&r==R){
return mx[o];
}else{
down(o);
int mid=(l+r)/2;
if(R<=mid) return ask(o*2,l,mid,L,R);
else if(L>mid)return ask(o*2+1,mid+1,r,L,R);
else return max(ask(o*2,l,mid,L,mid),
ask(o*2+1,mid+1,r,mid+1,R))

}
}
ask(1,1,n,L,R);


// 单点修改
// l,r线段树节点表示的区间,pos修改位置,w新的值
void modify(int o,int l,int r,int pos,int w){
if(l==r){
mx[o] = w;
}else{

down(o);
int mid=(l+r)/2;
if(pos<=mid){
//左边
modify(o*2,l,mid,pos,w);
}else{
//右边
modify(o*2+1,mid+1,r,pos,w);
}
mx[o]=max(mx[o*2],mx[o*2+1]);//快速合并
}
}

 

1 4 2 1 3

// 信息需要支持快速合并


// 新操作: 给位置在L~R的数字+x
Lazy 思想
如果一个区间被区间修改操作整个覆盖:
不用递归修改,建立一个lazy标记
如果真正访问下面节点,再下放标记
// o, l,r表示当前区间,L,R表示要修改的区间,表示要加的值
int lazy[];//存放标记
void down(int o){
if(lazy[o]!=0){
mx[o*2]+=lazy[o];
mx[o*2+1]+=lazy[o];
lazy[o*2]+=lazy[o];
lazy[o*2+1]+=lazy[o];
//清空标记
lazy[o]=0;
}
}
void add(int o,int l,int r,int L,int R,int w){
if(l==L&&r==R){
mx[o]+=w;
lazy[o]+=w;//对于子区间来说没有下放的标记
}else{
//下放标记
down(o);
int mid=(l+r)/2;
if(R<=mid) add(o*2,l,mid,L,R,w);//左
else if(L>mid) add(o*2+1,mid+1,r,L,R,w);//右
else{
add(o*2,l,mid,L,mid,w);
add(o*2+1,mid+1,r,mid+1,R,w));
}
}
mx[o]=max(mx[o*2],mx[o*2+1]);
}

线段树

标签:树节点   节点   标记   int   清空   思想   区间修改   信息   最大   

原文地址:https://www.cnblogs.com/DukeLv/p/8439369.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!