treap相对splay容易理解
对每个节点x,tr[x].rd=rand();
然后对tr[x].rd操作,使其满足堆性质
#include<bits/stdc++.h> #define maxn 1000005 #define ls tr[k].l #define rs tr[k].r using namespace std; int n,rt,size; struct tree{ int l,r,sz,cnt,rd,v; }tr[maxn]; inline int ran(){ static int seed = 2333; return seed = (int)((((seed ^ 998244353) + 19260817ll) * 19890604ll) % 1000000007); } void update(int k) { tr[k].sz=tr[ls].sz+tr[rs].sz+tr[k].cnt; } void lturn(int &k) { int t=rs;rs=tr[t].l;tr[t].l=k; tr[t].sz=tr[k].sz;update(k);k=t; } void rturn(int &k) { int t=ls;ls=tr[t].r;tr[t].r=k; tr[t].sz=tr[k].sz;update(k);k=t; } void insert(int &k,int x) { if(k==0) { ++size;k=size; tr[k].cnt=tr[k].sz=1; tr[k].v=x; tr[k].rd=ran(); return; } tr[k].sz++; if(x==tr[k].v)tr[k].cnt++; else if(x<tr[k].v) { insert(ls,x); if(tr[ls].rd<tr[k].rd)rturn(k); } else { insert(rs,x); if(tr[rs].rd<tr[k].rd)lturn(k); } } void del(int &k,int x) { if(k==0)return; if(tr[k].v==x) { if(tr[k].cnt>=2){tr[k].cnt--;tr[k].sz--;return;} if(ls==0||rs==0)k=ls+rs; else { if(tr[ls].rd<tr[rs].rd)rturn(k),del(k,x); else lturn(k),del(k,x); } } else if(tr[k].v<x)tr[k].sz--,del(rs,x); else tr[k].sz--,del(ls,x); } int find_pm(int k,int x) { if(k==0)return 0; if(tr[k].v==x)return tr[ls].sz+1; if(tr[k].v>x)return find_pm(ls,x); else return tr[ls].sz+tr[k].cnt+find_pm(rs,x); } int find_wz(int k,int x) { if(k==0)return 0; if(x<=tr[ls].sz)return find_wz(ls,x); else if(x>tr[ls].sz+tr[k].cnt)return find_wz(rs,x-tr[k].cnt-tr[ls].sz); else return tr[k].v; } int find_qq(int k,int x) { if(k==0)return -1e9; if(tr[k].v<x)return max(tr[k].v,find_qq(rs,x)); return find_qq(ls,x); } int find_hj(int k,int x) { if(k==0)return 1e9; if(tr[k].v>x)return min(tr[k].v,find_hj(ls,x)); return find_hj(rs,x); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { int temp,x; scanf("%d%d",&temp,&x); if(temp==1)insert(rt,x); if(temp==2)del(rt,x); if(temp==3)printf("%d\n",find_pm(rt,x)); if(temp==4)printf("%d\n",find_wz(rt,x)); if(temp==5)printf("%d\n",find_qq(rt,x)); if(temp==6)printf("%d\n",find_hj(rt,x)); } return 0; }