[CodeVs][1514][Treap][书架]

来源:互联网 发布:淘宝拉夏贝尔代购 编辑:程序博客网 时间:2024/05/20 07:58

这道题我全网就看到了一个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\n",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\n",get_rank(ptr[x]));else printf ("%d\n",rank(root, x));}return 0;}

That is all.Thank you for watching.

1 0
原创粉丝点击