传送门
按照紫荆花之恋的做法,动态维护一下点分树的形态
把点随机打乱
每次从当前的根开始 (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;
}
}
}
}
}