题意:
就是比普通平衡树多了一个持久化的操作
题解:
写起来和普通的平衡树没什么区别,因为fhq treap的根节点会变,所以要维护一下每个版本的根,然后在split的时候开个新点就好了(好像很多洛谷的题解在merge操作也开了新点,但是合并不会改变树的结点,所以开不开无所谓)
#include<iostream>
#include<sstream>
#include<string>
#include<queue>
#include<map>
#include<unordered_map>
#include<set>
#include<vector>
#include<stack>
#include <utility>
#include<algorithm>
#include<cstdio>
#include<list>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<time.h>
#include<random>
using namespace std;
#include<ext/pb_ds/priority_queue.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
#include<ext/rope>
using namespace __gnu_cxx;
#define int long long
#define PI acos(-1.0)
#define eps 1e-9
#define lowbit(a) ((a)&-(a))
#define endl '\n'
const int mod = 1e9+7;
int qpow(int a,int b){
int ans=1;
while(b){
if(b&1)ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
const int INF = 0x3f3f3f3f;
const int N = 1e6+10;
mt19937 rng(233);
struct node{
int l,r;
int key,siz,val;
}fhq[N*32];
int cnt,root[N],x,y,z;
void update(int now){fhq[now].siz=fhq[fhq[now].l].siz+fhq[fhq[now].r].siz+1;}
int newnode(int val){
fhq[++cnt]={0,0,rng(),1,val};
return cnt;
}
void split(int now,int val,int &x,int &y){
if(!now)x=y=0;
else{
if(fhq[now].val<=val){
fhq[x=++cnt]=fhq[now];
split(fhq[x].r,val,fhq[x].r,y);
update(x);
}
else{
fhq[y=++cnt]=fhq[now];
split(fhq[now].l,val,x,fhq[y].l);
update(y);
}
}
}
int merge(int x,int y){
if(!x||!y)return x|y;
if(fhq[x].key>fhq[y].key){
fhq[x].r=merge(fhq[x].r,y);
update(x);
return x;
}
else{
fhq[y].l=merge(x,fhq[y].l);
update(y);
return y;
}
}
void ins(int &root,int val){
split(root,val,x,y);
root=merge(merge(x,newnode(val)),y);
}
void del(int &root,int val){
split(root,val,x,z); split(x,val-1,x,y);
y=merge(fhq[y].l,fhq[y].r);
root=merge(merge(x,y),z);
}
void getrank(int &root,int val){
split(root,val-1,x,y);
cout<<fhq[x].siz+1<<endl;
root=merge(x,y);
}
void getnum(int root,int rank){
int now=root;
while(now){
if(fhq[fhq[now].l].siz+1==rank)break;
else if(fhq[fhq[now].l].siz>=rank)now=fhq[now].l;
else rank-=fhq[fhq[now].l].siz+1,now=fhq[now].r;
}
cout<<fhq[now].val<<endl;
}
void getpre(int &root,int val){
split(root,val-1,x,y);
if(!x){
cout<<-2147483647<<endl; return;
}
int now=x;
while(fhq[now].r)now=fhq[now].r;
cout<<fhq[now].val<<endl;
root=merge(x,y);
}
void getnext(int &root,int val){
split(root,val-1,x,y);
if(!y){
cout<<2147483647<<endl; return;
}
int now=y;
while(fhq[now].l)now=fhq[now].l;
cout<<fhq[now].val<<endl;
root=merge(x,y);
}
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int n; cin>>n;
for(int i=1;i<=n;i++){
int ver,opt,x; cin>>ver>>opt>>x;
root[i]=root[ver];
if(opt==1)ins(root[i],x);
if(opt==2)del(root[i],x);
if(opt==3)getrank(root[i],x);
if(opt==4)getnum(root[i],x);
if(opt==5)getpre(root[i],x);
if(opt==6)getnext(root[i],x);
}
}