#include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define root e[0].ch[1] const int maxn=100010; const int INF=233333333; struct node { int v,father; int ch[2]; int sum; int cnt; }; node e[maxn]; int n, points; void update(int x) { e[x].sum = e[e[x].ch[0]].sum + e[e[x].ch[1]].sum + e[x].cnt; } int identify(int x) { return e[e[x].father].ch[0] == x ? 0 : 1; } void connect(int x,int f,int son) { e[x].father=f; e[f].ch[son]=x; } void rotate(int x) { int y=e[x].father; int r=e[y].father; int rs=identify(y); int ys=identify(x); int B=e[x].ch[ys^1]; connect(B, y, ys); connect(y, x, (ys^1)); connect(x, r, rs); update(y); update(x); } void splay(int at,int to) { to=e[to].father; while(e[at].father!=to) { int up=e[at].father; if(e[up].father==to) rotate(at); else if(identify(up)==identify(at)) { //case1 rotate(up); rotate(at); } else { //case2 rotate(at); rotate(at); } } } void destroy(int x) { e[x].v=e[x].ch[0]=e[x].ch[1]=e[x].sum=e[x].father=e[x].cnt=0; if(x==n) n--; } int find(int v) { int now=root; while(true) { if(e[now].v==v) { splay(now,root); return now; } int next = v < e[now].v ? 0 : 1; if(!e[now].ch[next]) return 0; now=e[now].ch[next]; } } int crepoint(int v,int father) { n++; e[n].v=v; e[n].father=father; e[n].sum=e[n].cnt=1; return n; } int build(int v) { points++; if(points==1) { //空树 root=n+1; crepoint(v,0); } else { int now=root; while(true){ e[now].sum++; if(v==e[now].v) { e[now].cnt++; return now; } int next = v < e[now].v ? 0 : 1; if(!e[now].ch[next]) { crepoint(v,now); e[now].ch[next]=n; return n; } now=e[now].ch[next]; } } return 0; } void push(int v) { int add=build(v); splay(add, root); } void pop(int v) { int deal=find(v); if(!deal) return; points--; if(e[deal].cnt>1) { e[deal].cnt--; e[deal].sum--; return; } if(!e[deal].ch[0]) { root=e[deal].ch[1]; e[root].father=0; } else { int lef=e[deal].ch[0]; while(e[lef].ch[1]) lef=e[lef].ch[1]; splay(lef,e[deal].ch[0]); int rig=e[deal].ch[1]; connect(rig,lef,1); connect(lef,0,1); update(lef); } destroy(deal); } int Rank(int v) { int ans=0,now=root; while(true) { if(e[now].v==v) { ans=ans+e[e[now].ch[0]].sum+1; break; } if(now==0) return 0; if(v<e[now].v) now=e[now].ch[0]; else { ans=ans+e[e[now].ch[0]].sum+e[now].cnt; now=e[now].ch[1]; } } if(now) splay(now,root); return ans; } int atrank(int x) { if(x>points) return -INF; int now=root; while(true) { int ll=e[now].ch[0]; if(x<=e[ll].sum) now=e[now].ch[0]; else { if(x<=e[ll].sum+e[now].cnt) break; else x-=e[ll].sum+e[now].cnt, now=e[now].ch[1]; } } splay(now,root); return e[now].v; } int upper(int v) { int now=root, last=root; int result=INF; while(now) { if(e[now].v>v&&e[now].v<result) result=e[now].v, last=now; if(v<e[now].v) now=e[now].ch[0]; else now=e[now].ch[1]; } splay(last, root); return result; } int lower(int v) { int now=root, last=root; int result=-INF; while(now) { if(e[now].v<v&&e[now].v>result) result=e[now].v, last=now; if(v>e[now].v) now=e[now].ch[1]; else now=e[now].ch[0]; } splay(last, root); return result; } int main() { int t; cin>>t; for(int i=1; i<=t; i++) { int op, x; cin>>op>>x; if(op==1) push(x); else if(op==2) { pop(x); } else if(op==3) { cout<<Rank(x)<<endl; } else if(op==4) { cout<<atrank(x)<<endl; } else if(op==5) { cout<<lower(x)<<endl; } else { cout<<upper(x)<<endl; } } return 0; }
题解 https://www.luogu.org/problemnew/solution/P3369