HNOI2017单旋

HNOI2017单旋#

  • 观察题目的性质,发现单旋最小值或最大值时树的形态只是最值提到根, 原来的部分重新建一下边, 然后插入的时候一定是插入到前驱后继中较深的那一个的子树中, 且其子树对应位置一定非空。所以用\(set\)找前驱后继,树的形态直接用数组维护,线段树维护每个店的深度即可。
#include <bits/stdc++.h>

using std :: set;
using std :: pair;

typedef pair<int, int> Pii;
typedef long long ll;

inline int read(int x = 0, int _f = 0)
{
	char c = getchar();
	for (; !isdigit(c); c = getchar()) _f |= (c == '-');
	for (;  isdigit(c); c = getchar()) x = x*10 + c-'0';
	return _f? -x : x;
}

template <typename T> bool chkmax(T &a, T b) { return a < b? a = b, true : false; }
template <typename T> bool chkmin(T &a, T b) { return a > b? a = b, true : false; }

const int MAXN = 1e5 + 5;

int M;
int val[MAXN], N;

Pii q[MAXN];

inline int pos(int v)
{
	return std :: lower_bound(val + 1, val + N + 1, v) - val;
}

namespace SEGT
{

	#define lc (h << 1)
	#define rc (lc | 1)
	#define mid ((l + r) >> 1)
	
	ll sum[MAXN << 2], tag[MAXN << 2];

	inline void push_down(int h, int l, int r)
	{
		if (tag[h]) {
			sum[lc] += tag[h] * (mid - l + 1);
			sum[rc] += tag[h] * (r - mid);
			tag[lc] += tag[h];
			tag[rc] += tag[h];
			tag[h] = 0;
		}
	}

	void update(int h, int l, int r, int ql, int qr, int v)
	{
		if (qr < ql) return ;
		if (ql <= l && r <= qr) {
			tag[h] += v;
			sum[h] += (ll)v * (r - l + 1);
			return ;
		}
		push_down(h, l, r);
		if (ql <= mid) update(lc, l, mid, ql, qr, v);
		if (qr > mid) update(rc, mid + 1, r, ql, qr, v);
		sum[h] = sum[lc] + sum[rc];
	}

	void modify(int h, int l, int r, int p, int v)
	{
		if (l == r) {
			sum[h] = v;
			return ;
		}

		push_down(h, l, r);

		p <= mid? modify(lc, l, mid, p, v) : modify(rc, mid + 1, r, p, v);
		sum[h] = sum[lc] + sum[rc];
	}

	ll query(int h, int l, int r, int p)
	{
		if (l == r) return sum[h];

		push_down(h, l, r);

		return p <= mid? query(lc, l, mid, p) : query(rc, mid + 1, r, p);
	}

	#undef lc
	#undef rc
	#undef mid

}

set<int> S;
int fa[MAXN], ch[MAXN][2];
int rt;

inline int rotate_min()
{
	int u = pos(*S.begin()), depth = SEGT :: query(1, 1, N, u);

	if (depth != 1) {
		SEGT :: update(1, 1, N, fa[u], N, 1);
		SEGT :: modify(1, 1, N, u, 1);

		assert(fa[u] != 0);
		fa[ch[u][1]] = fa[u];
		ch[fa[u]][0] = ch[u][1];

		ch[u][1] = rt; fa[rt] = u; 
		rt = u; fa[rt] = 0;
	}
	else {
		assert(rt == u);
	}

	return depth;
}

inline int rotate_max()
{
	int u = pos(*(--S.end())), depth = SEGT :: query(1, 1, N, u);

	if (depth != 1) {
		SEGT :: update(1, 1, N, 1, fa[u], 1);
		SEGT :: modify(1, 1, N, u, 1);

		assert(fa[u] != 0);
		fa[ch[u][0]] = fa[u];
		ch[fa[u]][1] = ch[u][0];

		ch[u][0] = rt; fa[rt] = u;
		rt = u; fa[rt] = 0;
	}
	else {
		assert(rt == u);
	}

	return depth;
}

int main()
{
//	freopen("splay.in", "r", stdin);
//	freopen("splay.out", "w", stdout);

	M = read();
	for (int o = 1; o <= M; ++o) {

		q[o].first = read();

		if (q[o].first == 1) {
			q[o].second = read();
			val[++N] = q[o].second;
		}

	}

	std :: sort(val + 1, val + N + 1);

	for (int o = 1; o <= M; ++o) {

		int ty = q[o].first, v = q[o].second;

		if (ty == 1) {
			auto it = S.lower_bound(v);
			int dep1 = it == S.begin()? 0 : SEGT :: query(1, 1, N, pos(*prev(it)));
			int dep2 = it == S.end()? 0 : SEGT :: query(1, 1, N, pos(*it));

			if (dep1 + dep2 == 0) {
				fa[rt = pos(v)] = 0;
			}
			else if (dep1 > dep2) {
				fa[pos(v)] = pos(*prev(it));
				assert(ch[pos(*prev(it))][1] == 0);
				ch[pos(*prev(it))][1] = pos(v);
			}
			else if (dep2 > dep1) {
				fa[pos(v)] = pos(*it);
				assert(ch[pos(*it)][0] == 0);
				ch[pos(*it)][0] = pos(v);
			}
			else {
				assert(false);
			}

			SEGT :: modify(1, 1, N, pos(v), std::max(dep1, dep2) + 1);
			S.insert(v);

			printf("%d\n", std::max(dep1, dep2) + 1);
		}
		else if (ty == 2) {
			printf("%d\n", rotate_min());
		}
		else if (ty == 3) {
			printf("%d\n", rotate_max());
		}
		else if (ty == 4) {
			printf("%d\n", rotate_min());

			int u = pos(*S.begin());
			SEGT :: update(1, 1, N, u, N, -1);
			S.erase(S.begin());
			rt = ch[u][1];
			fa[rt] = 0;
			ch[u][1] = 0;
		}
		else {
			printf("%d\n", rotate_max());

			int u = pos(*(--S.end()));
			SEGT :: update(1, 1, N, 1, u, -1);
			S.erase((--S.end()));
			rt = ch[u][0];
			fa[rt] = 0;
			ch[u][0] = 0;
		}

	}

	return 0;
}

posted @ 2018-03-29 22:05  pbvrvnq  阅读(205)  评论(0编辑  收藏  举报