[luoguP2596] [ZJOI2006]书架(splay)

传送门

 

题目中的几个操作,直接splay搞一下即可:

  1. 把s旋转到根,左子树接到右子树
  2. 把s旋转到根,右子树接到左子树
  3. 交换s相邻的信息即可
  4. 把s旋转到根,左子树的大小即为答案
  5. 找第k大

没了

#include <cstdio>
#include <cstring>
#include <iostream>
#define N 100000

using namespace std;

int n, m, cnt, rt;
int son[N][2], size[N], f[N], pos[N], w[N];

inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0';
	return x * f;
}

inline int get(int x)
{
	return son[f[x]][1] == x;
}

inline void update(int x)
{
	size[x] = size[son[x][0]] + size[son[x][1]] + 1;
}

inline void rotate(int x)
{
	int fa = f[x], ffa = f[fa], p = get(x);
	son[fa][p] = son[x][p ^ 1], f[son[x][p ^ 1]] = fa;
	son[x][p ^ 1] = fa, f[fa] = x;
	if(ffa) son[ffa][son[ffa][1] == fa] = x; f[x] = ffa;
	update(fa), update(x);
}

inline void splay(int x, int y)
{
	for(int fa; (fa = f[x]) != y; rotate(x))
		if(f[fa] != y) rotate(get(fa) == get(x) ? fa : x);
	if(!y) rt = x;
}

inline void top_bottom(int x, int p)
{
	splay(pos[x], 0);
	if(!son[rt][p]) return;
	if(!son[rt][p ^ 1]) son[rt][p ^ 1] = son[rt][p], son[rt][p] = 0;
	else
	{
		x = son[rt][p ^ 1];
		while(son[x][p]) x = son[x][p];
		son[x][p] = son[rt][p], f[son[rt][p]] = x;
		son[rt][p] = 0, splay(son[x][p], 0);
	}
}

inline int build(int l, int r, int fa)
{
	if(l > r) return 0;
	int mid = (l + r) >> 1, now = ++cnt;
	son[now][0] = build(l, mid - 1, now);
	w[now] = read(), size[now] = 1, f[now] = fa, pos[w[now]] = now;
	son[now][1] = build(mid + 1, r, now);
	update(now);
	return now;
}

inline void ist(int p, int x)
{
	if(!p) return;
	splay(pos[x], 0);
	if(p == -1) p = 0;
	x = son[rt][p];
	while(son[x][p ^ 1]) x = son[x][p ^ 1];
	if(x) swap(pos[w[rt]], pos[w[x]]), swap(w[rt], w[x]);
}

inline void ask(int x)
{
	splay(pos[x], 0);
	printf("%d\n", size[son[rt][0]]);
}

inline int query(int k)
{
	int x = rt;
	while(x)
	{
		if(size[son[x][0]] + 1 == k) return w[x];
		else if(size[son[x][0]] >= k) x = son[x][0];
		else k -= size[son[x][0]] + 1, x = son[x][1];
	}
}

int main()
{
	int i, x;
	char s[10];
	n = read();
	m = read();
	rt = build(1, n, 0);
	for(i = 1; i <= m; i++)
	{
		scanf("%s", s);
		switch(s[0])
		{
			case 'T': top_bottom(read(), 0); break;
			case 'B': top_bottom(read(), 1); break;
			case 'I': ist(read(), read()); break;
			case 'A': ask(read()); break;
			case 'Q': printf("%d\n", query(read())); break;
		}
	}
	return 0;
}

  

 

posted @ 2018-01-17 18:24  zht467  阅读(225)  评论(0编辑  收藏  举报