空间消耗非常玄学,有多大开多大就完事了。
四个函数式查询,然后Merge的时候拷贝对应的xy子树,Split的时候拷贝p树。
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define ls(p) ch[p][0] #define rs(p) ch[p][1] const int MAXN = 30000000 + 5; int val[MAXN], ch[MAXN][2], rnd[MAXN], siz[MAXN], tot, root[MAXN]; void Init() { tot = 0; memset(root,0,sizeof(root)); } int NewNode(int v) { ++tot; ch[tot][0] = ch[tot][1] = 0; val[tot] = v, rnd[tot] = rand(); siz[tot] = 1; return tot; } int CopyNode(int p) { ++tot; ch[tot][0] = ch[p][0]; ch[tot][1] = ch[p][1]; val[tot] = val[p]; rnd[tot] = rnd[p]; siz[tot] = siz[p]; return tot; } void PushUp(int p) { siz[p] = siz[ls(p)] + siz[rs(p)] + 1; } void SplitValue(int p, int v, int &x, int &y) { if(!p) { x = y = 0; return; } if(v < val[p]) { y = CopyNode(p); SplitValue(ls(y), v, x, ls(y)); PushUp(y); } else { x = CopyNode(p); SplitValue(rs(x), v, rs(x), y); PushUp(x); } } /*void SplitRank(int p, int rk, int &x, int &y) { if(!p) { x = y = 0; return; } if(rk <= siz[ls(p)]) { y = p; SplitRank(ls(p), rk, x, ls(p)); PushUp(y); } else { x = p; SplitRank(rs(p), rk - siz[ls(p)] - 1, rs(p), y); PushUp(x); } }*/ int Merge(int x, int y) { if(!x || !y) return x | y; if(rnd[x] < rnd[y]) { int p = CopyNode(x); rs(p) = Merge(rs(p), y); PushUp(p); return p; } else { int p = CopyNode(y); ls(p) = Merge(x, ls(p)); PushUp(p); return p; } } void Insert(int &root, int v) { int x = 0, y = 0; SplitValue(root, v, x, y); root = Merge(Merge(x, NewNode(v)), y); } void Remove(int &root, int v) { int x = 0, y = 0, z = 0; SplitValue(root, v, x, z); SplitValue(x, v - 1, x, y); y = Merge(ls(y), rs(y)); root = Merge(Merge(x, y), z); } int GetRank2(int p, int v) { int rk = 1; while(p) { if(v < val[p]) p = ls(p); else if(v == val[p]) p = ls(p); else { rk += siz[ls(p)] + 1; p = rs(p); } } return rk; } int GetValue2(int p, int rk) { while(p) { if(rk <= siz[ls(p)]) p = ls(p); else if(rk == siz[ls(p)] + 1) return val[p]; else { rk -= siz[ls(p)] + 1; p = rs(p); } } } int GetPrev2(int p, int v) { int prev; while(p) { if(v <= val[p]) p = ls(p); else { prev = val[p]; p = rs(p); } } return prev; } int GetNext2(int p, int v) { int next; while(p) { if(v < val[p]) { next = val[p]; p = ls(p); } else p = rs(p); } return next; } int main() { #ifdef Yinku freopen("Yinku.in", "r", stdin); #endif // Yinku int n; scanf("%d", &n); Init(); for(int i = 1; i <= n; ++i) { int v,op, x; scanf("%d%d%d",&v, &op, &x); root[i]=root[v]; switch(op) { case 1: Insert(root[i], x); break; case 2: Remove(root[i], x); break; case 3: printf("%d\n", GetRank2(root[i], x)); break; case 4: printf("%d\n", GetValue2(root[i], x)); break; case 5: printf("%d\n", GetPrev2(root[i], x)); break; case 6: printf("%d\n", GetNext2(root[i], x)); break; } } return 0; }