【HNOI2017】单旋

题面

题解

trajan的spaly是O(1)的(逃

通过看题解手玩发现只要将最值的点放到树根,其他的父子关系不需要变。

于是想到动态连边和断边的数据结构:\(\mathrm{LCT}\),于是用\(\mathrm{LCT}\)维护\(\mathrm{splay}\)

这样后面的四个操作就解决了。

第一个操作中,第一个点要么接在前驱的右儿子,要么接在后继的左儿子。

于是再开个set求一下前驱后继即可。

代码

很多可以复制粘贴,所以也不算很长。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<set>
#include<map>
#define RG register
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define clear(x, y) memset(x, y, sizeof(x))

inline int read()
{
	int data = 0, w = 1; char ch = getchar();
	while(ch != '-' && (!isdigit(ch))) ch = getchar();
	if(ch == '-') w = -1, ch = getchar();
	while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
	return data * w;
}

const int maxn(200010);
int m, root, fa[maxn], son[2][maxn], stk[maxn], top;
int size[maxn], rev[maxn], cur, val[maxn], lson[maxn], rson[maxn], Fa[maxn];
inline bool isroot(int x) { return son[0][fa[x]] != x && son[1][fa[x]] != x; }
inline int  getSon(int x) { return son[1][fa[x]] == x; }
inline void update(int x) { size[x] = size[son[0][x]] + size[son[1][x]] + 1; }
inline void pushdown(int x)
{
	if(!rev[x]) return;
	rev[son[0][x]] ^= 1;
	rev[son[1][x]] ^= 1;
	rev[x] = 0, std::swap(son[0][x], son[1][x]);
}

inline void rotate(int x)
{
	int f = fa[x], g = fa[f], l = getSon(x), r = l ^ 1;
	if(!isroot(f)) son[getSon(f)][g] = x;
	fa[x] = g, fa[f] = x, fa[son[r][x]] = f;
	son[l][f] = son[r][x], son[r][x] = f;
	update(f), update(x);
}

void splay(int x)
{
	stk[top = 1] = x;
	for(int i = x; !isroot(i); i = fa[i]) stk[++top] = fa[i];
	while(top) pushdown(stk[top--]);
	for(; !isroot(x); rotate(x)) if(!isroot(fa[x]))
		rotate(getSon(fa[x]) ^ getSon(x) ? x : fa[x]);
}

void access(int x)
{
	for(int t = 0; x; t = x, x = fa[x])
		splay(x), son[1][x] = t, update(x);
}

inline void makeroot(int x) { access(x); splay(x); rev[x] ^= 1; }
inline void split(int x, int y) { makeroot(x); access(y); splay(y); }
inline int getdep(int x) { split(x, root); return size[root]; }
inline void link(int x, int y) { makeroot(x); fa[x] = y; }
inline void cut(int x, int y)
{
	split(x, y); if(son[0][y] == x) son[0][y] = 0;
	fa[x] = 0;
}

std::map<int, int> map;
std::set<int> set;

void insert(int x)
{
	int now = map[x] = ++cur;
	if(set.empty()) return (void) (set.insert(x), root = now, puts("1"));
	std::set<int>::iterator it = set.upper_bound(x);
	if(it == set.end() || lson[map[*it]])
	{
		--it; int node = map[*it]; link(now, node);
		Fa[now] = node, rson[node] = now;
	}
	else
	{
		int node = map[*it]; link(now, node);
		Fa[now] = node, lson[node] = now;
	}
	set.insert(x); printf("%d\n", getdep(now));
}

void splay_min()
{
	int x = map[*set.begin()];
	if(root == x) return (void) (puts("1"));
	printf("%d\n", getdep(x)); cut(x, Fa[x]);
	if(rson[x]) cut(x, rson[x]);
	link(x, root); if(rson[x]) link(Fa[x], rson[x]);
	lson[Fa[x]] = rson[x]; if(rson[x]) Fa[rson[x]] = Fa[x];
	Fa[x] = 0, Fa[root] = x, rson[x] = root; root = x;
}

void splay_max()
{
	int x = map[*set.rbegin()];
	if(root == x) return (void) (puts("1"));
	printf("%d\n", getdep(x)); cut(x, Fa[x]);
	if(lson[x]) cut(x, lson[x]);
	link(x, root); if(lson[x]) link(lson[x], Fa[x]);
	rson[Fa[x]] = lson[x]; if(lson[x]) Fa[lson[x]] = Fa[x];
	Fa[x] = 0, Fa[root] = x, lson[x] = root; root = x;
}

void del_min()
{
	int x = map[*set.begin()];
	if(root == x)
	{
		puts("1"); if(rson[x]) cut(x, rson[x]);
		Fa[rson[x]] = 0; root = rson[x];
		set.erase(set.begin()); return;
	}
	printf("%d\n", getdep(x)); cut(x, Fa[x]);
	if(rson[x]) cut(x, rson[x]), link(Fa[x], rson[x]);
	lson[Fa[x]] = rson[x]; if(rson[x]) Fa[rson[x]] = Fa[x];
	set.erase(set.begin());
}

void del_max()
{
	int x = map[*set.rbegin()];
	if(root == x)
	{
		puts("1"); if(lson[x]) cut(x, lson[x]);
		Fa[lson[x]] = 0; root = lson[x];
		set.erase(--set.end()); return;
	}
	printf("%d\n", getdep(x)); cut(x, Fa[x]);
	if(lson[x]) cut(x, lson[x]), link(lson[x], Fa[x]);
	rson[Fa[x]] = lson[x]; if(lson[x]) Fa[lson[x]] = Fa[x];
	set.erase(--set.end());
}

int main()
{
	m = read();
	for(RG int i = 1; i <= m; i++)
	{
		int opt = read();
		switch(opt)
		{
			case 1: insert(read()); break;
			case 2: splay_min(); break;
			case 3: splay_max(); break;
			case 4: del_min(); break;
			case 5: del_max(); break;
		}
	}
	return 0;
}
posted @ 2019-02-25 14:33  xgzc  阅读(187)  评论(0编辑  收藏  举报