zoukankan      html  css  js  c++  java
  • 【YBTOJ】【Luogu P2596】[ZJOI2006]书架

    链接:

    洛谷

    题目大意:

    维护一个序列,支持移动元素,查询某元素位置,查询某位置元素。

    正文:

    考虑用 fhq-Treap。

    主要解决 fhq-Treap 不能通过编号找节点的问题。假设我们要求下图红点的位置:

    可以每次往父亲节点跳,如果它右孩子则编号就要加上左孩子大小加一,这个一实际上是父亲的零头。也就是说,只要维护了父亲节点就能求出位置。

    这样下来,就是 fhq-Treap 基本操作了。

    代码:

    int read()
    {
    	int f = 1, x = 0;
    	char c = getchar();
    	while (c < '0' || c > '9') {if(c == '-')f = -f;c = getchar();}
    	while (c >= '0' && c <= '9')x = x * 10 + c - '0', c= getchar();
    	return f * x;
    }
    
    const int N = 1e5 + 10;
    
    int n, m;
    string s;
    
    struct FHQ_Treap
    {
    	struct BST
    	{
    		int ch[2], fa, siz, dat, val;
    	}t[N];
    	
    	FHQ_Treap() {srand(1919810);} 
    	
    	int tot, root, id[N];
    	int New(int val)
    	{
    		t[++tot].siz = 1,
    		t[tot].val = val,
    		t[tot].dat = rand();
    		return tot; 
    	}
    	
    	void Update(int x) 
    	{ 
    		t[x].siz = 1;
    		if (t[x].ch[0]) t[x].siz += t[t[x].ch[0]].siz, t[t[x].ch[0]].fa = x;
    		if (t[x].ch[1]) t[x].siz += t[t[x].ch[1]].siz, t[t[x].ch[1]].fa = x; 
    	}
    	
    	int Merge(int x, int y)
    	{
    		if (!x || !y) return x + y;
    		if (t[x].dat < t[y].dat)
    		{
    			t[x].ch[1] = Merge(t[x].ch[1], y);
    			Update(x);
    			return x;
    		}else
    		{
    			t[y].ch[0] = Merge(x, t[y].ch[0]);
    			Update(y);
    			return y;
    		}
    	}
    	
    	void Split(int x, int kth, int &l, int &r)
    	{
    		if (!x) { l = r = 0;return;} 
    		if (t[t[x].ch[0]].siz < kth)
    			l = x, Split(t[x].ch[1], kth - t[t[x].ch[0]].siz - 1, t[x].ch[1], r);
    		else
    			r = x, Split(t[x].ch[0], kth, l, t[x].ch[0]);
    		Update(x);
    	}
    	
    	int Pos(int x)
    	{
    		int ans = 1 + t[t[x].ch[0]].siz;
    		for (; t[x].fa; x = t[x].fa)
    			if (x == t[t[x].fa].ch[1])
    				ans += t[t[t[x].fa].ch[0]].siz + 1;
    		return ans;
    	}
    }t;
    
    int main()
    {
    //	freopen(".in", "r", stdin);
    //	freopen(".out", "w", stdout);
    	scanf ("%d%d", &n, &m);
    	for (int i = 1, x; i <= n; i++)
    		scanf ("%d", &x), t.id[x] = i, t.root = t.Merge(t.root, t.New(x));
    	for (int i = 1; i <= m; i++)
    	{
    		cin >> s;
    		int x = read();
    		int y = t.Pos(t.id[x]);
    		if (s[0] == 'T') 
    		{
    			int a, b, c;
    			t.Split(t.root, y - 1, a, b);
    			t.Split(b, 1, b, c);
    			t.root = t.Merge(b, t.Merge(a, c));
    			continue;
    		} 
    		if (s[0] == 'B') 
    		{
    			int a, b, c;
    			t.Split(t.root, y - 1, a, b);
    			t.Split(b, 1, b, c);
    			t.root = t.Merge(a, t.Merge(c, b));
    			continue;
    		} 
    		 
    		if (s[0] == 'I') 
    		{
    			int G = read();
    			if (!G) continue;
    			
    			int a, b, c, d;
    			t.Split(t.root, y - 1 - (G == -1), a, b);
    			t.Split(b, 1, b, c);
    			t.Split(c, 1, c, d);
    			t.root = t.Merge(a, t.Merge(t.Merge(c, b), d));
    			continue;
    		} 
    		
    		if (s[0] == 'A')
    		{
    			printf ("%d
    ", y - 1);
    			continue;
    		}
    		int a, b, c;
    		t.Split(t.root, x - 1, a, b);
    		t.Split(b, 1, b, c);
    		printf ("%d
    ", t.t[b].val);
    		t.root = t.Merge(t.Merge(a, b), c);
    	}
        return 0;
    }
    
    
  • 相关阅读:
    [INS-32033] Central Inventory location is not writable
    ORACLE中的PL/SQL
    Oracle几大后台进程
    2016年中山市信息学竞赛暨全国信息学联赛成绩表(普及组)
    NOIP复习资料——往年习题精选
    迪杰斯特拉dijkstar(算法个人观点)
    【USACO题库】1.4.2 The Clocks时钟.TJ
    【USACO题库】2.1.2 Ordered Fractions顺序的分数.tj
    纪中2016.10.6比赛不明总结
    纪中2016.8.17比赛不明总结
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14413585.html
Copyright © 2011-2022 走看看