非旋转 Treap/fhq Treap
权值版
宏定义
#define fhqT int:以 为基本类型维护,可根据自己需要定义,这里实现了以 为基本类型的 。#define pl a[p].l: 中左子树的简写。#define pr a[p].r: 中右子树的简写。
常量与变量
-
tot:实际存在的节点个数。 -
nc[i]:第 个内存(没有被占用的节点)。 -
root: 的根节点,一般为 。 -
a[i]: 的一个节点 。 -
a[i].l:节点 的左子节点,没有则为 。 -
a[i].r:节点 的右子节点,没有则为 。 -
a[i].val:节点 的值。 -
a[i].size:以节点 为根的子树的元素总数(值相同的不算作一个)。 -
a[i].dat:随机的额外权值,以确定 的形态。
函数
FHQ_Treap():初始化相关信息,不必调用。-
update(int p):更新 节点的 。 -
get_new(fhqT val):新建一个值为 的节点,返回这个节点的编号。 -
split(int p,fhqT val,int &x,int &y):把节点 以 值分裂。 -
merge(int p,int q):合并 节点和 节点。 -
insert(fhqT val):在树中插入一个值为 的节点。 -
remove(fhqT val):删除一个值为 的节点。 -
get_val(int p,int rank):找到以 为根的子树中排名为 的节点的值。 -
get_rank(fhqT val):找到树中值为 的节点的排名。 -
get_pre(fhqT val):找到树中值为 的元素的前驱的节点的值。 -
get_next(fhqT val):找到树中值为 的元素的后驱的节点的值。 -
write(int p):输出以 节点为根节点的子树的信息,按先序遍历输出,每个节点的信息包括:该节点编号,该节点值,左子节点编号及值(无则均为 ),右子节点编号及值(无则均为 )。
#define fhqT int
#define pl a[p].l
#define pr a[p].r
struct FHQ_Treap{
struct Tree{
int l,r;
fhqT val;
int size,dat;
}a[N],e;
int tot,root;
int x,y,z;
int nc[N];
FHQ_Treap(){
root=0;
tot=N-1;
e.l=e.r=e.val=e.dat=e.size=0;
for(int i=1;i<N;i++)
a[i]=e,nc[i]=i;
}
void update(int p){
a[p].size=a[pl].size+a[pr].size+1;
}
int get_new(fhqT val){
int p=tot--;
a[p]=e;
a[p].val=val;
a[p].dat=rand();
a[p].size=1;
return p;
}
void split(int p,fhqT val,int &x,int &y){
if(!p){
x=y=0;
return;
}
if(a[p].val<=val){
x=p;
split(pr,val,pr,y);
}
else{
y=p;
split(pl,val,x,pl);
}
update(p);
}
int merge(int p,int q){
if(!p||!q)
return p+q;
if(a[p].dat<a[q].dat){
a[p].r=merge(a[p].r,q);
update(p);
return p;
}
a[q].l=merge(p,a[q].l);
update(q);
return q;
}
void insert(fhqT val){
split(root,val,x,y);
root=merge(merge(x,get_new(val)),y);
}
void remove(fhqT val){
split(root,val,x,z);
split(x,val-1,x,y);
nc[++tot]=y;
y=merge(a[y].l,a[y].r);
root=merge(merge(x,y),z);
}
fhqT get_val(int p,int rank){
if(rank<=a[pl].size)
return get_val(pl,rank);
if(rank==a[pl].size+1)
return a[p].val;
return get_val(pr,rank-a[pl].size-1);
}
int get_rank(fhqT val){
split(root,val-1,x,y);
int ans=a[x].size+1;
root=merge(x,y);
return ans;
}
fhqT get_pre(fhqT val){
split(root,val-1,x,y);
fhqT ans=get_val(x,a[x].size);
root=merge(x,y);
return ans;
}
fhqT get_next(fhqT val){
split(root,val,x,y);
fhqT ans=get_val(y,1);
root=merge(x,y);
return ans;
}
void write(int p){
if(pl)
write(pl);
printf("%d %d %d %d %d %d\n",p,a[p].val,pl,pr,a[pl].val,a[pr].val);
if(pr)
write(pr);
}
}tree;
区间版
以P2042 [NOI2005] 维护数列为标准。
宏定义
#define fhqT int:以 为基本类型维护,可根据自己需要定义,这里实现了以 为基本类型的 。#define pl a[p].l: 中左子树的简写。#define pr a[p].r: 中右子树的简写。
常量与变量
-
tot:实际存在的节点个数。 -
nc[i]:第 个内存(没有被占用的节点)。 -
add[i]:将加入的第 个数。 -
root: 的根节点,一般为 。 -
a[i]: 的一个节点 。 -
a[i].l:节点 的左子节点,没有则为 。 -
a[i].r:节点 的右子节点,没有则为 。 -
a[i].val:节点 的值。 -
a[i].sum:以节点 为根的树的值总和。 -
a[i].mx:区间最大子段和。 -
a[i].lmx:以左端点为起点的最大子段和。 -
a[i].rmx:以右端点为起点的最大子段和。 -
a[i].size:以节点 为根的子树的元素总数(值相同的不算作一个)。 -
a[i].dat:随机的额外权值,以确定 的形态。 -
a[i].tag1:区间赋值标记。 -
a[i].tag2:区间翻转标记。
函数
FHQ_Treap():初始化相关信息,不必调用。-
update(int p):更新 节点的 。 -
get_new(fhqT val):新建一个值为 的节点,返回这个节点的编号。 -
pushup(int p):把 子树的信息上传。 -
make_same(int p,fhqT c):把以 为根的子树的节点的值全部赋值为 。 -
reverse(int p):把 子树翻转。 -
pushdown(int p):下传 节点的标记。 -
split(int p,int rank,int &x,int &y):把节点 以 排名分裂。 -
merge(int p,int q):合并 节点和 节点。 -
get_l_to_r(int l,int r):把区间 分裂出来并返回根节点的值。 -
merge_back():把树合并回来。 -
add_num(int l,int r):递归加入 数组中 到 的数。 -
insert(int rank,int n):在区间 位置后插入 数组的前 个数。 -
del_num(int p):删除以 为根的子树。 -
remove(int rank,int n):删除在区间 位置后的 个数。 -
get_sum(int p):以 为根的子树的总值和。 -
get_mx(int p):以 为根的子树的最大子段和。 -
write(int p):输出以 节点为根节点的子树的信息,按先序遍历输出,每个节点的信息包括:该节点编号,该节点值,左子节点编号及值(无则均为 ),右子节点编号及值(无则均为 ),注意这个操作会把所有节点pushdown一遍,要慎用。
#define fhqT int
#define pl a[p].l
#define pr a[p].r
struct FHQ_Treap{
struct Tree{
int l,r;
fhqT val,sum,mx,lmx,rmx;
int size,dat;
int tag1,tag2;
}a[N];
int tot,root;
int x,y,z;
int nc[N];
fhqT add[N];
FHQ_Treap(){
root=0;
tot=N-1;
Tree e;
e.l=e.r=e.val=e.dat=e.size=0;
e.sum=e.tag1=e.tag2=0;e.lmx=e.rmx=e.mx=0;
for(int i=0;i<N;i++)
a[i]=e,nc[i]=i;
}
int get_new(fhqT val){
int p=nc[tot--];
a[p].sum=a[p].mx=a[p].val=val;
a[p].dat=rand();
a[p].size=1;
a[p].tag1=a[p].tag2=a[p].l=a[p].r=0;
a[p].lmx=a[p].rmx=max(0,val);
return p;
}
void pushup(int p){
if(!p)
return;
a[p].size=a[pl].size+a[pr].size+1;
a[p].sum=a[pl].sum+a[p].val+a[pr].sum;
a[p].lmx=max(a[pl].lmx,a[pl].sum+a[p].val+a[pr].lmx);
a[p].rmx=max(a[pr].rmx,a[pr].sum+a[p].val+a[pl].rmx);
a[p].mx=a[pl].rmx+a[p].val+a[pr].lmx;
if(pl)
a[p].mx=max(a[p].mx,a[pl].mx);
if(pr)
a[p].mx=max(a[p].mx,a[pr].mx);
}
void make_same(int p,fhqT c){
a[p].val=c;
a[p].sum=a[p].size*c;
a[p].lmx=a[p].rmx=max(0,a[p].sum);
a[p].mx=max(c,a[p].sum);
a[p].tag1=1;
}
void reverse(int p){
swap(pl,pr);
swap(a[p].lmx,a[p].rmx);
a[p].tag2^=1;
}
void pushdown(int p){
if(!p)
return;
if(a[p].tag1){
if(pl)
make_same(pl,a[p].val);
if(pr)
make_same(pr,a[p].val);
a[p].tag1=0;
}
if(a[p].tag2){
if(pl)
reverse(pl);
if(pr)
reverse(pr);
a[p].tag2=0;
}
}
void split(int p,int rank,int &x,int &y){
if(!p){
x=y=0;
return;
}
pushdown(p);
if(a[pl].size<rank){
x=p;
split(pr,rank-a[pl].size-1,pr,y);
}
else{
y=p;
split(pl,rank,x,pl);
}
pushup(p);
}
int merge(int p,int q){
if(!p||!q)
return p+q;
if(a[p].dat<a[q].dat){
pushdown(p);
a[p].r=merge(a[p].r,q);
pushup(p);
return p;
}
pushdown(q);
a[q].l=merge(p,a[q].l);
pushup(q);
return q;
}
int get_l_to_r(int l,int r){
split(root,l-1,x,y);
split(y,r-l+1,y,z);
return y;
}
void merge_back(){
root=merge(merge(x,y),z);
}
int add_num(int l,int r){
int mid=(l+r)>>1;
if(l^r)
return merge(add_num(l,mid),add_num(mid+1,r));
return get_new(add[l]);
}
void insert(int rank,int n){
split(root,rank,x,y);
root=merge(merge(x,add_num(1,n)),y);
}
void del_num(int p){
if(!p)
return;
nc[++tot]=p;
del_num(pl);
del_num(pr);
}
void remove(int rank,int n){
split(root,rank-1,x,y);
split(y,n,y,z);
del_num(y);
root=merge(x,z);
}
int get_sum(int p){
return a[p].sum;
}
int get_mx(int p){
return a[p].mx;
}
void write(int p){
if(!p)
return;
pushdown(p);
write(pl);
printf("%d %d %d %d %d %d\n",p,a[p].val,pl,pr,a[pl].val,a[pr].val);
write(pr);
}
}tree;

浙公网安备 33010602011771号