您的位置:首页 > 其它

简单的线段树

2017-11-07 21:10 127 查看

前言

线段树想必大家再熟悉不过了,说实话敲线段树的模板还是很享受的(温馨提示:不要被数据结构所驾驭了)。

这里,蒟蒻我就简要说一下鄙人的线段树的一些简单功能:支持单点、区间更新,求单点权值,区间求和、最值。

struct Tree{
#define lson L,mid,p<<1
#define rson mid+1,R,p<<1|1
#define family tree[p],tree[p<<1],tree[p<<1|1]
#define root 1,n,1
struct node{
int L,R;
int sum,add;
int Mx,Mn;
}tree[N<<2];
void Up(node &A,node L,node R){
A.sum=L.sum+R.sum;
A.Mx=max(L.Mx,R.Mx);
A.Mn=min(L.Mn,R.Mn);
}
void Down(node &A,node &L,node &R){
int &t=A.add;
if(!t)return;
L.add+=t;
R.add+=t;
L.sum+=t*(L.R-L.L+1);
R.sum+=t*(R.R-R.L+1);
t=0;
}
void build(int L,int R,int p){
tree[p].L=L,tree[p].R=R;
tree[p].sum=tree[p].add=0;
if(L==R){
//          tree[p].sum=A[L];
return;
}
int mid=(L+R)>>1;
build(lson),build(rson);
Up(family);
}
void update_one(int x,int res,int p){
if(tree[p].L==tree[p].R){
tree[p].sum+=res;
return;
}
int mid=(tree[p].L+tree[p].R)>>1;
if(x<=mid)update_one(x,res,p<<1);
else update_one(x,res,p<<1|1);
Up(family);
}
void update_interval(int L,int R,int p,int res){
if(tree[p].L==L && tree[p].R==R){
tree[p].add+=res;
tree[p].sum+=1LL*res*(R-L+1);
return;
}
Down(family);
int mid=(tree[p].L+tree[p].R)>>1;
if(R<=mid)update_interval(L,R,p<<1,res);
else if(L>mid)update_interval(L,R,p<<1|1,res);
else update_interval(lson,res),update_interval(rson,res);
Up(family);
}
//注意求单点只需要沿途加上sum即可,不用Down
int query_one(int x,int p){
int mid=(tree[p].L+tree[p].R)>>1;
if(x<=mid)return tree[p].sum+query_one(x,p<<1);
else return tree[p].sum+query_one(x,p<<1|1);
}
int query_interval(int L,int R,int p){
if(tree[p].L==L && tree[p].R==R)return tree[p].sum;
Down(family);
int mid=(tree[p].L+tree[p].R)>>1;
if(R<=mid)return query_interval(L,R,p<<1);
else if(L>mid)return query_interval(L,R,p<<1|1);
else return query_interval(lson)+query_interval(rson);
}
int query_Max(int L,int R,int p){
if(tree[p].L==L && tree[p].R==R)return tree[p].Mx;
int mid=(tree[p].L+tree[p].R)>>1;
if(R<=mid)return query_Max(L,R,p<<1);
else if(L>mid)return query_Max(L,R,p<<1|1);
else return max(query_Max(lson),query_Max(rson));
}
int query_Min(int L,int R,int p){
if(tree[p].L==L && tree[p].R==R)return tree[p].Mn;
int mid=(tree[p].L+tree[p].R)>>1;
if(R<=mid)return query_Min(L,R,p<<1);
else if(L>mid)return query_Min(L,R,p<<1|1);
else return min(query_Min(lson),query_Min(rson));
}
}Tree;


小结:

线段树是一个非常好用的东西,是常用于维护区间的某些值的数据结构之一。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: