【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\n", y - 1);
			continue;
		}
		int a, b, c;
		t.Split(t.root, x - 1, a, b);
		t.Split(b, 1, b, c);
		printf ("%d\n", t.t[b].val);
		t.root = t.Merge(t.Merge(a, b), c);
	}
    return 0;
}

posted @ 2021-02-18 21:38  Jayun  阅读(53)  评论(0编辑  收藏  举报