zoukankan      html  css  js  c++  java
  • [CodeVs][1514][Treap][书架]


    这道题我全网就看到了一个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.

  • 相关阅读:
    SQL Server的Execute As与连接池结合使用的测试
    为什么SQL语句Where 1=1 and在SQL Server中不影响性能
    [转]NGINX下配置CACHE-CONTROL
    ls列出当前目录包含子目录下面的所有文件的绝对路径
    [转]无法滚动到溢出容器的Flex项的顶部
    align-items和align-content的区别
    go实现快速排序
    [转]linux超级服务器inetd详解
    makefile 小记
    [转]gcc
  • 原文地址:https://www.cnblogs.com/dcoi-king/p/7491438.html
Copyright © 2011-2022 走看看