UOJ#349. 【WC2018】即时战略

传送门
按照紫荆花之恋的做法,动态维护一下点分树的形态
把点随机打乱
每次从当前的根开始 (explore),如果已经有了就暴力跳到那个点
否则加入这个点
注意一条链的要单独处理

# include <bits/stdc++.h>
# include "rts.h"
using namespace std;
typedef long long ll;

const int maxn(3e5 + 5);
const double alpha(0.7);

int n, first[maxn], cnt, deep[maxn], frt[maxn], vis[maxn], idx, root;
int sz[maxn], nsz, mx[maxn], rt, mark[maxn], size[maxn], id[maxn], see[maxn];

struct Edge {
	int to, next;
} edge[maxn << 1];

inline void Add(int u, int v) {
	edge[cnt] = (Edge){v, first[u]}, first[u] = cnt++;
	edge[cnt] = (Edge){u, first[v]}, first[v] = cnt++;
}

void Clear(int u, int ff) {
	int e, v;
	mark[u] = 0;
	for (e = first[u]; ~e; e = edge[e].next)
		if (((v = edge[e].to) ^ ff) && (vis[v] ^ idx)) Clear(v, u);
}

void Getroot(int u, int ff) {
	int e, v;
	sz[u] = 1, mx[u] = 0;
	for (e = first[u]; ~e; e = edge[e].next)
		if (((v = edge[e].to) ^ ff) && (vis[v] ^ idx)) {
			Getroot(v, u);
			sz[u] += sz[v], mx[u] = max(mx[u], sz[v]);
		}
	mx[u] = max(mx[u], nsz - sz[u]);
	if (!rt || mx[u] < mx[rt]) rt = u;
}

void Build(int u) {
	int e, v;
	vis[u] = idx;
	for (e = first[u]; ~e; e = edge[e].next)
		if (vis[v = edge[e].to] ^ idx) {
			rt = 0, nsz = sz[v], Getroot(v, u);
			frt[rt] = u, size[rt] = sz[v], Build(rt);
		}
}

inline void Rebuild(int u) {
	int x;
	for (++idx, x = frt[u]; x; x = frt[x]) vis[x] = idx;
	Clear(u, 0), rt = 0, nsz = size[u], Getroot(u, 0);
	if (u == root) root = rt;
	frt[rt] = frt[u], size[rt] = sz[u], Build(rt);
}

void Update(int u, int v) {
	if (!frt[u]) {
		if (mark[u]) Rebuild(u);
		return;
	}
	++size[frt[u]];
	if (frt[u] && alpha * size[frt[u]] < size[u]) mark[frt[u]] = 1;
	Update(frt[u], v);
	if (mark[u]) Rebuild(u);
}

void play(int n, int T, int dataType) {
	int i, cur = 1, l, r, p;
	for (i = 2; i <= n; ++i) id[i] = i;
	srand(time(NULL)), random_shuffle(id + 2, id + n + 1);
	if (dataType == 3) {
		see[1] = l = r = 1;
		for (i = 2; i <= n; ++i) {
			if (see[id[i]]) continue;
			p = explore(l, id[i]);
			if (!see[p]) {
				l = p;
				while (l ^ id[i]) see[l] = 1, l = explore(l, id[i]);
			}
			else {
				p = explore(r, id[i]), r = p;
				while (r ^ id[i]) see[r] = 1, r = explore(r, id[i]);
			}
			see[id[i]] = 1;
		}
	}
	else {
		memset(first, -1, sizeof(first));
		size[cur] = see[1] = root = 1;
		for (i = 2; i <= n; ++i) {
			cur = root;
			while (!see[id[i]]) {
				p = explore(cur, id[i]);
				if (see[p]) {
					while (cur ^ frt[p]) p = frt[p];
					cur = p;
				}
				else {
					Add(cur, p);
					frt[p] = cur, size[p] = 1;
					Update(p, p), see[p] = 1;
					cur = p;
				}
			}
		}
	}
}
原文地址:https://www.cnblogs.com/cjoieryl/p/10279637.html