( ext{Solution:})
考虑用 fhq_treap 来实现这个东西。
每次的新建版本,我们可以新建一个根,并直接利用 merge 和 split 操作在上一个版本上利用信息。
注意 split 和 merge 中都需要新建节点,否则会影响之前版本的结构。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN=5e5+10;
const int INF=1000000001;
const int N=MAXN<<6;
int rt[MAXN],tr[N][2];
int siz[N],cv[N],val[N];
int cnt;
inline int read() {
int s=0,w=1;
char ch=getchar();
while(!isdigit(ch)) {
if(ch=='-')w=-1;
ch=getchar();
}
while(isdigit(ch)) {
s=s*10-48+ch;
ch=getchar();
}
return w*s;
}
inline int rd(){return rand()<<15|rand();}
inline int bd(int v){
val[++cnt]=v;
siz[cnt]=1;
cv[cnt]=rd();
return cnt;
}
inline void pushup(int x){siz[x]=siz[tr[x][0]]+siz[tr[x][1]]+1;}
void split(int now,int k,int &x,int &y){
if(!now){x=y=0;return;}
if(val[now]<=k){
x=++cnt;
tr[x][0]=tr[now][0];
tr[x][1]=tr[now][1];
val[x]=val[now];
siz[x]=siz[now];
cv[x]=cv[now];
split(tr[x][1],k,tr[x][1],y);
pushup(x);
}
else{
y=++cnt;
tr[y][0]=tr[now][0];
tr[y][1]=tr[now][1];
val[y]=val[now];
siz[y]=siz[now];
cv[y]=cv[now];
split(tr[y][0],k,x,tr[y][0]);
pushup(y);
}
}
int merge(int x,int y){
if(!x||!y)return x+y;
if(cv[x]<cv[y]){
int p=++cnt;
tr[p][0]=tr[x][0];
tr[p][1]=tr[x][1];
val[p]=val[x];
siz[p]=siz[x];
cv[p]=cv[x];
tr[p][1]=merge(tr[p][1],y);
pushup(p);return p;
}
else{
int p=++cnt;
tr[p][0]=tr[y][0];
tr[p][1]=tr[y][1];
siz[p]=siz[y];
val[p]=val[y];
cv[p]=cv[y];
tr[p][0]=merge(x,tr[p][0]);
pushup(p);return p;
}
}
void del(int &root,int v){
int xA=0,yA=0,zA=0;
split(root,v,xA,zA);
split(xA,v-1,xA,yA);
yA=merge(tr[yA][0],tr[yA][1]);
root=merge(merge(xA,yA),zA);
}
void Ins(int &root,int v){
int x=0,y=0;
split(root,v,x,y);
root=merge(merge(x,bd(v)),y);
}
int n,opt;
int kth(int now,int k){
if(k<=siz[tr[now][0]])return kth(tr[now][0],k);
if(k==siz[tr[now][0]]+1)return now;
return kth(tr[now][1],k-siz[tr[now][0]]-1);
}
void dfs(int x){
if(tr[x][0])dfs(tr[x][0]);
printf("%lld ",val[x]);
if(tr[x][1])dfs(tr[x][1]);
}
signed main(){
n=read();
// dfs(rt[0]);puts("");
for(int i=1;i<=n;++i){
int v=read(),x;
opt=read();x=read();
rt[i]=rt[v];
if(opt==1){Ins(rt[i],x);}
else if(opt==2){del(rt[i],x);}
else if(opt==3){
int A=0,B=0;
split(rt[i],x-1,A,B);
printf("%lld
",siz[A]+1);
rt[i]=merge(A,B);
}
else if(opt==4){printf("%lld
",val[kth(rt[i],x)]);}
else if(opt==5){
int A=0,B=0;
split(rt[i],x-1,A,B);
if(!A){
puts("-2147483647");
continue;
}
printf("%lld
",val[kth(A,siz[A])]);
rt[i]=merge(A,B);
}
else{
int A=0,B=0;
split(rt[i],x,A,B);
if(!B){
puts("2147483647");
continue;
}
printf("%lld
",val[kth(B,1)]);
rt[i]=merge(A,B);
}
// dfs(rt[i]);puts("");
}
return 0;
}
注意没有前驱后继的处理,不能在一开始就加进去,那样的排名是不对的。
细节上就是注意新开节点。