这道题我全网就看到了一个treap,QAQ
这道题有个难题,他每次是对一个编号的书进行操作,如果是对从左到右的一个排名的书进行操作还好办.....
因此在网上一位大神的代码帮助下,我发现,可以在外界对每一个书的编号搞一个指针,然后用get_rank函数来求出这本书的排名,然后就很好搞了。。。
get_rank 怎么写呢? 我们将当前节点往父亲爬,直到爬到根,如果当前节点是其父亲的右儿子,那么rank就加上父亲的左儿子的大小,再加上1(父亲的大小)
由于要往上爬,当然要记录父亲了,在update里维护一下就好。
上代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cctype> #include<string> #include<cstdlib> #include<cmath> #include<cctype> const int N = 8e4 + 9; struct Treap { int id, size, hr; Treap *l, *r, *fa; Treap () {} Treap (int id, Treap *fl) : id(id),size(1),hr(rand()),l(fl),r(fl),fa(fl) {} void update () { size = l -> size + r -> size + 1; l -> fa = r -> fa = this; } }*root, meme[N], *pool = meme, *Null; Treap* newnode (int xxx) { return new (pool++) Treap (xxx, Null); } using std :: pair; typedef pair <Treap*,Treap*> Droot; Droot Split (Treap *x,int k) { if(x == Null) return Droot (Null, Null); Droot y; if(x -> l -> size >= k) { y = Split (x -> l, k); x -> l = y . second; x -> update (); y . second = x; } else { y = Split (x -> r, k - x -> l -> size - 1); x -> r = y . first; x -> update (); y . first = x; } return y; } Treap* Merge (Treap *A,Treap *B) { if(A == Null) return B; if(B == Null) return A; if(A -> hr > B -> hr) { B -> l = Merge (A, B -> l); B -> update (); return B; } else { A -> r = Merge (A -> r, B); A -> update (); return A; } } Treap *ptr[N]; int n,m,id[N]; Treap* Build () { static Treap *stk[N], *last, *x; int top = 0; for (int i = 1; i <= n; ++i) { last = Null; ptr[id[i]] = x = newnode (id[i]); while (top && x -> hr < stk[top] -> hr) { stk[top] -> update (); last = stk[top--]; } if(top) stk[top] -> r = x,x -> fa = stk[top]; x -> l = last; last -> fa = x; stk[++top] = x; } while (top) stk[top--] -> update (); return stk[1]; } int get_rank (Treap *x) { // 有了getrank我们就可以搞事情了.... int res = x -> l -> size; while (x -> fa != Null) { if (x == x -> fa -> r) res += x -> fa -> l -> size + 1; x = x -> fa; } return res; } void puton (int xxx, bool v) { static Droot clc1,clc2; int k = get_rank (ptr[xxx]); clc1 = Split (root, k); clc2 = Split (clc1.second,1); if(v) root = Merge(Merge(clc2.first,clc1.first),clc2.second); else root = Merge (clc1.first,Merge(clc2.second,clc2.first)); } void bookon (int xxx,int opt) { if(!opt) return ; static Droot clc1,clc2,clc3; int k = get_rank (ptr[xxx]); clc1 = Split (root, k); clc2 = Split (clc1.second, 1); if(opt == -1) clc1 = Split(clc1.first, clc1.first -> size - 1), root = Merge (Merge(clc1.first,clc2.first),Merge(clc1.second,clc2.second)); else clc3 = Split(clc2.second, 1), root = Merge (Merge(clc1.first, clc3.first), Merge(clc2.first,clc3.second)); } int getin () { int num = 0; char a; bool fl = false; for (a = getchar(); a < '0' || a > '9'; a = getchar()) if(a == '-') fl = true; for (; a >= '0' && a <= '9'; a = getchar()) num = (num << 3) + (num << 1) + a - '0'; if(fl) num = -num; return num; } int rank (Treap *x, int k) { if (x -> l -> size >= k) return rank (x -> l, k); if (x -> l -> size + 1 == k) return x -> id; return rank (x -> r, k - x -> l -> size - 1); } char opt[23]; int x; void Print (Treap *x) { if(x == Null) return ; Print (x -> l); printf("%d ",x -> id); Print (x -> r); } bool it (Treap *xx) { if(xx == Null) return 0; bool ok = 0; ok |= it (xx -> l); ok |= it (xx -> r); return ok || xx->fa==Null || xx->fa->l==xx || xx->fa->r==xx; } int main () { freopen ("1514.in","r",stdin); freopen ("1514.out","w",stdout); Null = new Treap (); Null -> size = 0; scanf("%d%d",&n,&m); for (int i = 1; i <= n; ++i) id[i] = getin (); root = Build (); for (int i = 1; i <= m; ++i) { scanf("%s%d",opt,&x); if(opt[0] == 'T') puton (x, true); else if(opt[0] == 'B') puton (x, false); else if(opt[0] == 'I') bookon (x, getin()); else if(opt[0] == 'A') printf ("%d ",get_rank(ptr[x])); else printf ("%d ",rank(root, x)); } return 0; }
That is all.Thank you for watching.