线段树套有旋 Treap
部分内容与 的相同,这里已省略,重点讲解线段树部分的功能。
另外,代码建树时需要一个辅助数组 代表第 个数的初始值。
宏定义
- :线段树中点 的左儿子。
- :线段树中点 的右儿子。
变量
- :已使用的节点总数。
- :预留的第 个内存位。
- :极大值。
- :平衡树的节点。
- :有旋 部分。
- :线段树节点结构体。
- :线段树节点。
- :节点 所管理的区间的左端点。
- :节点 所管理的区间的右端点。
- :节点 所管理的区间的平衡树。
函数
- :初始化 。
- :建树。
- :将树中位置为 的值由原来的 修改为 。
- :求 在区间 内的排名减去 。
- :求区间 内排名为 的数。
- :求 内值为 的数的前驱,若不存在则返回 。
- :求 内值为 的数的后继,若不存在则返回 。
代码
int tot,nc[N*20];
int INF=2147483647;
struct Tree{
int l,r,dat,sz,cnt;
int val;
}a[N*20];
struct Treap{
int rt;
void pushup(int p){
a[p].sz=a[a[p].l].sz+a[a[p].r].sz+a[p].cnt;
}
int get_new(int val){
int p=nc[++tot];
a[p].l=a[p].r=0;a[p].dat=rand();
a[p].sz=a[p].cnt=1;a[p].val=val;
return p;
}
void del(int &p){
nc[tot--]=p;p=0;
}
void build(){
rt=get_new(-INF);
a[rt].r=get_new(INF);pushup(rt);
}
void zig(int &p){
int q=a[p].l;
a[p].l=a[q].r;a[q].r=p;p=q;
pushup(a[p].r);pushup(p);
}
void zag(int &p){
int q=a[p].r;
a[p].r=a[q].l;a[q].l=p;p=q;
pushup(a[p].l);pushup(p);
}
void insert(int &p,int val){
if(!p){
p=get_new(val);return;
}
if(a[p].val==val){
a[p].cnt++;pushup(p);
return;
}
if(val<a[p].val){
insert(a[p].l,val);
if(a[a[p].l].dat>a[p].dat)zig(p);
}
else{
insert(a[p].r,val);
if(a[a[p].r].dat>a[p].dat)zag(p);
}
pushup(p);
}
void remove(int &p,int val){
if(!p)return;
if(a[p].val==val){
if(a[p].cnt>1){
a[p].cnt--;pushup(p);
return;
}
if(a[p].l||a[p].r){
if(!a[p].r||a[a[p].l].dat>a[a[p].r].dat){
zig(p);remove(a[p].r,val);
}
else{
zag(p);remove(a[p].l,val);
}
pushup(p);return;
}
else del(p);
return;
}
if(val<a[p].val)remove(a[p].l,val);
else remove(a[p].r,val);
pushup(p);
}
int VtoR(int p,int val){
if(!p)return 0;
if(val<a[p].val)return VtoR(a[p].l,val);
if(val==a[p].val)return a[a[p].l].sz;
return a[a[p].l].sz+a[p].cnt+VtoR(a[p].r,val);
}
int pre(int val){
int ans=1,p=rt;
while(p){
if(val==a[p].val){
if(a[p].l){
p=a[p].l;
while(a[p].r)p=a[p].r;
ans=p;
}
break;
}
if(a[p].val<val&&a[p].val>a[ans].val)
ans=p;
p=(val<a[p].val?a[p].l:a[p].r);
}
return a[ans].val;
}
int nxt(int val){
int ans=2,p=rt;
while(p){
if(val==a[p].val){
if(a[p].r){
p=a[p].r;
while(a[p].l)p=a[p].l;
ans=p;
}
break;
}
if(a[p].val>val&&a[p].val<a[ans].val)
ans=p;
p=(val<a[p].val?a[p].l:a[p].r);
}
return a[ans].val;
}
void dfs(int p){
if(a[p].l)dfs(a[p].l);
printf("(%d,%d) ",p,a[p].val);
if(a[p].r)dfs(a[p].r);
}
};
#define pl p<<1
#define pr p<<1|1
struct Segmet{
Segmet(){
srand(time(0));tot=0;
for(int i=1;i<N*20;i++)nc[i]=i;
}
struct Tree{
int l,r;
Treap t;
}s[N<<2];
void build(int p,int l,int r){
s[p].l=l;s[p].r=r;s[p].t.build();
for(int i=l;i<=r;i++)
s[p].t.insert(s[p].t.rt,b[i]);
if(l==r)return;
int mid=(l+r)>>1;
build(pl,l,mid);build(pr,mid+1,r);
}
void change(int p,int x,int lv,int nv){
s[p].t.remove(s[p].t.rt,lv);
s[p].t.insert(s[p].t.rt,nv);
if(s[p].l==s[p].r)return;
int mid=(s[p].l+s[p].r)>>1;
if(x<=mid)change(pl,x,lv,nv);
else change(pr,x,lv,nv);
}
int VtoR(int p,int l,int r,int val){
if(l<=s[p].l&&s[p].r<=r){
return s[p].t.VtoR(s[p].t.rt,val)-1;
}
int mid=(s[p].l+s[p].r)>>1;
int ans=0;
if(l<=mid)ans+=VtoR(pl,l,r,val);
if(r>mid)ans+=VtoR(pr,l,r,val);
return ans;
}
int RtoV(int l,int r,int rank){
ll L=0,R=1e8;
while(L<R){
ll mid=(L+R+1)>>1;
if(VtoR(1,l,r,mid)+1<=rank)L=mid;
else R=mid-1;
}
return L;
}
int pre(int p,int l,int r,int val){
if(l<=s[p].l&&s[p].r<=r)
return s[p].t.pre(val);
int mid=(s[p].l+s[p].r)>>1;
int ans=-INF;
if(l<=mid)ans=max(ans,pre(pl,l,r,val));
if(r>mid)ans=max(ans,pre(pr,l,r,val));
return ans;
}
int nxt(int p,int l,int r,int val){
if(l<=s[p].l&&s[p].r<=r)
return s[p].t.nxt(val);
int mid=(s[p].l+s[p].r)>>1;
int ans=INF;
if(l<=mid)ans=min(ans,nxt(pl,l,r,val));
if(r>mid)ans=min(ans,nxt(pr,l,r,val));
return ans;
}
}tree;

浙公网安备 33010602011771号