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;
                }
            }
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/cjoieryl/p/10279637.html