https://www.luogu.org/problemnew/show/P3369
知识点:1.拆分split,合并merge
2.split,merge要点:通过传址调用来简便代码
3.记得root = merge(xxxxx,xxxxx);
2 wrong in code
#include <bits/stdc++.h> #define M 200002 using namespace std; int tot = 0; int val[M],rd[M]; int ch[M][2]; int root = 0; int m; int siz[M]; int newnode(int x) { siz[++tot] = 1; val[tot] = x; rd[tot] = rand(); return tot; } void updata(int x) { siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1; } void split(int now,int k,int &x,int &y) { if(!now) { x = y = 0; return; } else { if(val[now] <= k) { x = now; split(ch[now][1],k,ch[now][1],y); } else { y = now; split(ch[now][0],k,x,ch[now][0]); } updata(now); } } int merge(int A,int B) { if(!A || !B) return A + B; if(rd[A] < rd[B]){ch[A][1] = merge(ch[A][1],B); updata(A); return A;} else {ch[B][0] = merge(A,ch[B][0]); updata(B); return B;} } void insert(int t) { int x,y; split(root,t,x,y); root = merge(merge(x,newnode(t)),y); } void del(int t) { int x,y,z; split(root,t,x,z); split(x,t - 1,x,y);//wrong 1:是 split(x,t - 1,x,y)而不是 split(root,t - 1,x,y) y = merge(ch[y][0],ch[y][1]);//wrong 2: 记得y = root = merge(merge(x,y),z); } int findrk(int t) { int x,y; split(root,t - 1,x,y); int ans = siz[x] + 1; root = merge(x,y); return ans; } int kth(int now,int k) { while(now) { if(k <= siz[ch[now][0]]) now = ch[now][0]; else if(k == siz[ch[now][0]] + 1) return now; else k -= siz[ch[now][0]] + 1,now = ch[now][1]; } return now; } int front(int k) { int x,y; split(root,k - 1,x,y); int ans = val[kth(x,siz[x])]; root = merge(x,y); return ans; } int back(int k) { int x,y; split(root,k,x,y); int ans = val[kth(y,1)]; root = merge(x,y); return ans; } int main() { srand(1); scanf("%d",&m); int x,y; while(m--) { scanf("%d%d",&x,&y); if(x == 1) { insert(y); } if(x == 2) { del(y); } if(x == 3) { printf("%d ",findrk(y)); } if(x == 4) { printf("%d ",val[kth(root,y)]); } if(x == 5) { printf("%d ",front(y)); } if(x == 6) { printf("%d ",back(y)); } } return 0; }