1、线段树
线段树Lazy操作模板(区间修改,区间查询)
class Segment_Tree_Lazy{
private:
#define ls (p<<1)
#define rs ((p<<1)|1)
#define mid ((l+r)>>1)
int val[100010],cnt[100010];
inline void updata(int p){
val[p]=val[ls]+val[rs];
}
inline void add(int p,int v,int t){
val[p]+=v*t;
cnt[p]+=v;
}
inline void pushdown(int p,int l,int r){
if(!cnt[p])
return ;
add(ls,cnt[p],mid-l+1);
add(rs,cnt[p],r-mid);
cnt[p]=0;
}
public:
inline void build_tree(int p,int l,int r){
cnt[p]=0;
if(l==r){
val[p]=a[l];
return ;
}
build_tree(ls,l,mid);
build_tree(rs,mid+1,r);
updata(p);
}
inline void change(int p,int l,int r,int x,int y,int t){
if(x<=l&&r<=y){
add(p,t,r-l+1);
return ;
}
pushdown(p,l,r);
if(x<=mid)
change(ls,l,mid,x,y,t);
if(y>mid)
change(rs,mid+1,r,x,y,t);
updata(p);
}
inline int ask(int p,int l,int r,int x,int y){
if(x<=l&&r<=y)
return val[p];
int ans=0;
pushdown(p,l,r);
if(x<=mid)
ans+=ask(ls,l,mid,x,y);
if(y>mid)
ans+=ask(rs,mid+1,r,x,y);
return ans;
}
}S;
二维线段树模板(单点修改,区间查询)
class Segment_Tree_xy{
private:
#define ls(p) (p<<1)
#define rs(p) ((p<<1)|1)
#define mid ((l+r)>>1)
int tree[5000][5000];
inline void updata(int px,int py){
tree[px][py]=tree[px][ls(py)]+tree[px][rs(py)];
}
public:
inline void change_y(int py,int l,int r,int y,int t,int px){
if(l==r){
tree[px][py]+=t;
return ;
}
if(y<=mid)
change_y(ls(py),l,mid,y,t,px);
if(y>mid)
change_y(rs(py),mid+1,r,y,t,px);
updata(px,py);
}
inline void change_x(int px,int l,int r,int x,int y,int t){
if(l==r){
change_y(1,1,n,y,t,px);
return ;
}
if(x<=mid)
change_x(ls(px),l,mid,x,y,t);
if(x>mid)
change_x(rs(px),mid+1,r,x,y,t);
change_y(1,1,n,y,t,px);
}
inline int ask_y(int py,int l,int r,int y1,int y2,int px){
if(y1<=l&&r<=y2)
return tree[px][py];
int ans=0;
if(y1<=mid)
ans+=ask_y(ls(py),l,mid,y1,y2,px);
if(y2>mid)
ans+=ask_y(rs(py),mid+1,r,y1,y2,px);
return ans;
}
inline int ask_x(int px,int l,int r,int x1,int y1,int x2,int y2){
if(x1<=l&&r<=x2)
return ask_y(1,1,n,y1,y2,px);
int ans=0;
if(x1<=mid)
ans+=ask_x(ls(px),l,mid,x1,y1,x2,y2);
if(x2>mid)
ans+=ask_x(rs(px),mid+1,r,x1,y1,x2,y2);
return ans;
}
}S;
线段树标记永久化模板(标记不下传,主要用于李超线段树与主席树等)
class Tag_Forever_Segment_Tree{
public:
#define ls (p<<1)
#define rs ((p<<1)|1)
#define mid ((l+r)>>1)
int val[100010],tag[100010];
inline void updata(int p){
val[p]=val[ls]+val[rs];
}
inline void build_tree(int p,int l,int r){
if(l==r){
val[p]=a[l];
return ;
}
build_tree(ls,l,mid);
build_tree(rs,mid+1,r);
updata(p);
}
inline void change(int p,int l,int r,int x,int y,int t){
val[p]+=(y-x+1)*t;
if(x<=l&&r<=y){
tag[p]+=t;
return ;
}
if(y<=mid)
change(ls,l,mid,x,y,t);
if(x>mid)
change(rs,mid+1,r,x,y,t);
if(y>mid&&x<=mid){
change(ls,l,mid,x,mid,t);
change(rs,mid+1,r,mid+1,y,t);
}
}
inline int ask(int p,int l,int r,int x,int y,int sum){
if(l==r)
return sum+val[p];
if(y<=mid)
return ask(ls,l,mid,x,y,sum+tag[p]);
if(x>mid)
return ask(rs,mid+1,r,x,y,sum+tag[p]);
if(y>mid&&x<=mid){
return ask(ls,l,mid,x,mid,sum+tag[p])+ask(rs,mid+1,r,mid+1,y,sum+tag[p]);
}
}
}T;
线段树合并模板
class Mergable_Segment{
public:
#define mid ((l+r)>>1)
int val[100010],ls[100010],rs[100010],pnt_num;
inline void updata(int p){
val[p]=val[ls[p]]+val[rs[p]];
}
public:
inline void change(int &p,int l,int r,int x){
if(!p)
p=++pnt_num;
if(l==r){
val[p]=1;
return ;
}
if(x<=mid)
change(ls[p],l,mid,x);
else
change(rs[p],mid+1,r,x);
updata(p);
}
inline int query(int p,int l,int r,int x){
if(x>val[p])
return 0;
if(l==r)
return l;
if(val[ls[p]]>=x)
return query(ls[p],l,mid,x);
else
return query(rs[p],mid+1,r,x-val[ls[p]]);
}
inline int merge(int a,int b){
if(!a||!b)
return a+b;
ls[a]=merge(ls[a],ls[b]);
rs[a]=merge(rs[a],rs[b]);
updata(a);
return a;
}
}M;
class Persistable_Segment_Tree{
private:
#define mid ((l+r)>>1)
int pntnum,ls[20000010],rs[20000010],tree[20000010];
//ls[i]为i的左儿子,rs[i]为i的右儿子,tree[i]为i的值
public:
inline void clear(){//清空操作
pntnum=0;//节点数置为0
mem(tree,0);mem(ls,0);mem(rs,0);//清空数组
}
inline void build_tree(int &pos,int l,int r){
pos=++pntnum;//添加新节点,当前节点编号为++pntnum
if(l==r){
tree[pos]=val[l];//初始化每个叶节点的值
return ;
}
build_tree(ls[pos],l,mid);
build_tree(rs[pos],mid+1,r);
}
inline void change(int &pos,int vsn,int l,int r,int loc,int val){//pos新版本的当前节点编号,vsn旧版本的当前节点编号,l左端点,r右端点,loc要修改的节点编号,val修改值
pos=++pntnum;//新建节点
if(l==r){
tree[pos]=val;//修改值
return ;
}
ls[pos]=ls[vsn];//继承旧版本左子树
rs[pos]=rs[vsn];//继承旧版右左子树
if(loc<=mid)//如果要修改的节点在左子树中
change(ls[pos],ls[vsn],l,mid,loc,val);//处理左子树
else
change(rs[pos],rs[vsn],mid+1,r,loc,val);//处理右子树
}
inline int ask(int vsn,int l,int r,int loc){//vsn要访问的版本的当前节点编号,l左端点,r右端点,loc要访问的节点编号
if(l==r)
return tree[vsn];
if(loc<=mid)//如果在左子树中
return ask(ls[vsn],l,mid,loc);
else
return ask(rs[vsn],mid+1,r,loc);
}
}P;