非旋treap
基本操作
简述
\(FHQ\) \(treap\)借用了\(treap\)的特点,基于\(split\)和\(merge\)操作实现,因其不用旋转,又叫非旋\(treap\),优点是好理解,上手快,代码短 (ps: 重点是好写)
#define ls(x) t[x].ch[0]
#define rs(x) t[x].ch[1]
struct tree{
int sz,val,pri,ch[2];
}t[N<<2];
il int add(cs int val){
t[++cnt].sz=1;
t[cnt].val=val;
t[cnt].pri=srd();
return cnt;
}
il void upd(cs int rt){
t[rt].sz=1+t[ls(rt)].sz+t[rs(rt)].sz;
}
分裂
这里是按照权值分裂,小于等于\(k\)的在左边(\(x\)),大于的在右边(\(y\)),也可以按子树大小分
il void split(cs int rt,cs int k,int &x,int &y){
if(!rt) x=y=0;
else{
if(t[rt].val<=k) x=rt,split(rs(rt),k,rs(x),y);
else y=rt,split(ls(rt),k,x,ls(y));
t[rt].sz=1+t[ls(rt)].sz+t[rs(rt)].sz;//
}
return;
}
合并
要保证\(x\)的权值(子树大小)比\(y\)的小,具体看分裂按什么分
il int merge(cs int x,cs int y){ //val[x]<val[y]
if(!x||!y) return x+y;
if(t[x].pri<t[y].pri){
rs(x)=merge(rs(x),y);
t[x].sz=1+t[ls(x)].sz+t[rs(x)].sz;
return x;
}
else{
ls(y)=merge(x,ls(y));
t[y].sz=1+t[ls(y)].sz+t[rs(y)].sz;
return y;
}
}
\(insert\)
to be continue~
il void ins(int &rt,cs int val){
ri int x,y;
split(rt,val,x,y);
rt=merge(merge(x,add(val)),y);
return;
}
\(delete\)
to be continue~
il void del(int &rt,cs int val){
ri int x,y,z;
split(rt,val,x,z),split(x,val-1,x,y);
y=merge(ls(y),rs(y));
rt=merge(merge(x,y),z);
return;
}
查询\(k\)的排名
to be continue~
il int rnk(int &rt,cs int val){
ri int x,y,as;
split(rt,val-1,x,y);
as=t[x].sz+1,rt=merge(x,y);
return as;
}
查询排名为\(k\)的数
to be continue~
il int kth(cs int rt,int k){
ri int o=rt;
while(1){//rt=0
if(k<=t[ls(o)].sz) o=ls(o);
else if(k==t[ls(o)].sz+1) return o;//
else k-=t[ls(o)].sz+1,o=rs(o);//
}
}
查询\(k\)的前驱
to be continue~
il int pre(int &rt,cs int val){
ri int x,y,as;
split(rt,val-1,x,y);
as=t[kth(x,t[x].sz)].val;
rt=merge(x,y);
return as;
}
查询\(k\)的后继
to be continue~
il int nxt(int &rt,cs int val){
ri int x,y,as;
split(rt,val,x,y);
as=t[kth(y,1)].val;
rt=merge(x,y);
return as;
}
AC·code
#include <bits/stdc++.h>
#define il inline
#define cs const
#define ri register
#define F(s) freopen(#s".in","r",stdin),freopen(#s".out","w",stdout);
using namespace std;
namespace Q{
il int rd(){
ri int x=0;ri bool f=0;ri char c=getchar();
while(!isdigit(c)) f|=(c==45),c=getchar();
while(isdigit(c)) x=x*10+(c^48),c=getchar();
return f?-x:x;
}
il void wt(int x){
if(x<0) x=-x,putchar(45);
if(x>=10) wt(x/10);
return putchar(x%10|48),void();
}
il void wn(int x,char c=10){
wt(x),putchar(c);
}
} using namespace Q;
cs int N=1e5+5;
int cnt,rot,n;
mt19937 srd(time(0));
namespace fhq_treap{
#define ls(x) t[x].ch[0]
#define rs(x) t[x].ch[1]
struct tree{
int sz,val,pri,ch[2];
}t[N<<2];
il int add(cs int val){
t[++cnt].sz=1;
t[cnt].val=val;
t[cnt].pri=srd();
return cnt;
}
il void split(cs int rt,cs int k,int &x,int &y){
if(!rt) x=y=0;
else{
if(t[rt].val<=k) x=rt,split(rs(rt),k,rs(x),y);
else y=rt,split(ls(rt),k,x,ls(y));
t[rt].sz=1+t[ls(rt)].sz+t[rs(rt)].sz;//
}
return;
}
il int merge(cs int x,cs int y){
if(!x||!y) return x+y;
if(t[x].pri<t[y].pri){
rs(x)=merge(rs(x),y);
t[x].sz=1+t[ls(x)].sz+t[rs(x)].sz;
return x;
}
else{
ls(y)=merge(x,ls(y));
t[y].sz=1+t[ls(y)].sz+t[rs(y)].sz;
return y;
}
}
il void del(int &rt,cs int val){
ri int x,y,z;
split(rt,val,x,z),split(x,val-1,x,y);
y=merge(ls(y),rs(y));
rt=merge(merge(x,y),z);
return;
}
il void ins(int &rt,cs int val){
ri int x,y;
split(rt,val,x,y);
rt=merge(merge(x,add(val)),y);
return;
}
il int rnk(int &rt,cs int val){
ri int x,y,as;
split(rt,val-1,x,y);
as=t[x].sz+1,rt=merge(x,y);
return as;
}
il int kth(cs int rt,int k){
ri int o=rt;
while(1){//rt=0
if(k<=t[ls(o)].sz) o=ls(o);
else if(k==t[ls(o)].sz+1) return o;//
else k-=t[ls(o)].sz+1,o=rs(o);//
}
}
il int pre(int &rt,cs int val){
ri int x,y,as;
split(rt,val-1,x,y);
as=t[kth(x,t[x].sz)].val;
rt=merge(x,y);
return as;
}
il int nxt(int &rt,cs int val){
ri int x,y,as;
split(rt,val,x,y);
as=t[kth(y,1)].val;
rt=merge(x,y);
return as;
}
} using namespace fhq_treap;
signed main(){
n=rd();
for(ri int i=1,op,x;i<=n;++i){
op=rd(),x=rd();
switch (op){
case 1: ins(rot,x); break;
case 2: del(rot,x); break;
case 3: wn(rnk(rot,x)); break;
case 4: wn(t[kth(rot,x)].val); break;
case 5: wn(pre(rot,x)); break;
default: wn(nxt(rot,x));break;
}
}
return 0;
}
区间翻转
把 \([l, r]\) 分裂出来(按子树大小),打上懒标记,再合并回去,记得下放懒标记
il void rev(int &rt,int l,int r){
ri int x,y,z;
split(rt,r,x,z),split(x,l-1,x,y);
t[y].lz^=1,rt=merge(merge(x,y),z);
}
\(split\)有一点差异
il void split(cs int rt,cs int k,int &x,int &y){
if(!rt) x=y=0;
else{
pushdown(rt);
if(t[ls(rt)].sz<k){ //要减去左儿子的size!
x=rt,split(rs(rt),k-t[ls(rt)].sz-1,rs(x),y);
}
else y=rt,split(ls(rt),k,x,ls(y));
t[rt].sz=1+t[ls(rt)].sz+t[rs(rt)].sz;//
}
return;
}
\(merge\) 要在合并前下放标记
il int merge(cs int x,cs int y){//sz[x]<sz[y]
if(!x||!y) return x+y;
if(t[x].pri<t[y].pri){
pushdown(x);
rs(x)=merge(rs(x),y);
t[x].sz=1+t[ls(x)].sz+t[rs(x)].sz;
return x;
}
else{
pushdown(y);
ls(y)=merge(x,ls(y));
t[y].sz=1+t[ls(y)].sz+t[rs(y)].sz;
return y;
}
}
AC·code
#include <bits/stdc++.h>
#define il inline
#define cs const
#define ri register
#define F(s) freopen(#s".in","r",stdin),freopen(#s".out","w",stdout);
using namespace std;
namespace Q{
il int rd(){
ri int x=0;ri bool f=0;ri char c=getchar();
while(!isdigit(c)) f|=(c==45),c=getchar();
while(isdigit(c)) x=x*10+(c^48),c=getchar();
return f?-x:x;
}
il void wt(int x){
if(x<0) x=-x,putchar(45);
if(x>=10) wt(x/10);
return putchar(x%10|48),void();
}
} using namespace Q;
cs int N=1e5+5;
int cnt,rot,n,m;
mt19937 srd(time(0));
namespace fhq_treap{
#define ls(x) t[x].ch[0]
#define rs(x) t[x].ch[1]
struct tree{
int sz,val,pri,ch[2],lz;
}t[N<<2];
il void pushdown(int rt){
if(t[rt].lz){
t[rt].lz=0;
swap(ls(rt),rs(rt));
t[ls(rt)].lz^=1;
t[rs(rt)].lz^=1;
}
}
il int add(cs int val){
t[++cnt].sz=1;
t[cnt].val=val;
t[cnt].pri=srd();
return cnt;
}
il void split(cs int rt,cs int k,int &x,int &y){
if(!rt) x=y=0;
else{
pushdown(rt);
if(t[ls(rt)].sz<k){
x=rt,split(rs(rt),k-t[ls(rt)].sz-1,rs(x),y);
}
else y=rt,split(ls(rt),k,x,ls(y));
t[rt].sz=1+t[ls(rt)].sz+t[rs(rt)].sz;//
}
return;
}
il int merge(cs int x,cs int y){//sz[x]<sz[y]
if(!x||!y) return x+y;
if(t[x].pri<t[y].pri){
pushdown(x);
rs(x)=merge(rs(x),y);
t[x].sz=1+t[ls(x)].sz+t[rs(x)].sz;
return x;
}
else{
pushdown(y);
ls(y)=merge(x,ls(y));
t[y].sz=1+t[ls(y)].sz+t[rs(y)].sz;
return y;
}
}
il void rev(int &rt,int l,int r){
ri int x,y,z;
split(rt,r,x,z),split(x,l-1,x,y);
t[y].lz^=1,rt=merge(merge(x,y),z);
}
il void prt(int rt){
pushdown(rt);
if(ls(rt)) prt(ls(rt));
wt(t[rt].val),putchar(32);
if(rs(rt)) prt(rs(rt));
}
} using namespace fhq_treap;
signed main(){
n=rd(),m=rd();
for(ri int i=1;i<=n;++i){
rot=merge(rot,add(i));
}
for(ri int i=1,l,r;i<=m;++i){
l=rd(),r=rd(),rev(rot,l,r);
}
prt(rot);
return 0;
}