Codeforces Round #621 (Div. 1 + Div. 2)

Codeforces Round #621 (Div. 1 + Div. 2)

A

B

C

只需计算长度为 (1,2) 的(略)

D

E

大概观察一下,划分可行的条件为:吃同种草的最多有两只,一只左一只右;并且左边走得最远的和右边走得最远的不会碰到。

枚举左边的羊向右到达的最远点,然后依次考虑每种 (f_i) ,看看能不能往左边、右边塞。最大数量和方案数都可以按照题意模拟求出来

F

先预处理两两休息点之间是否能到达。以 (frac{k}{2}) 为最大距离进行多源 (bfs) ,用并查集维护。如果 (k) 为奇数,把所有边长度改为 (2) 且在中间加入额外节点即可。

对于询问 ((x,y)),先判断 (dist(x,y)leq k),若不满足则必须依靠休息点。那么往各往对方的方向走 (frac{k}{2}) 步,然后判断是否在同一个集合中。

int n, k, r, a[N], f[N];
int d[N], fa[N][19], vis[N];
vector<int> g[N];
#define pb push_back
struct node { int u, d; } ; queue<node> q;
int get (int x) { return x == f[x] ? x : f[x] = get (f[x]); }
void merge (int x, int y) { f[get (x)] = get (y); }
void bfs () {
    for (int i = 1; i <= r; ++i)
        q.push ({a[i], 0}), vis[a[i]] = 1;
    while (!q.empty()) {
        node p = q.front (); q.pop ();
        if (p.d == k) continue;
        for (int v : g[p.u]) {
            merge (v, p.u);
            if (!vis[v]) vis[v] = 1, q.push ({v, p.d + 1});
        }
    }
}
void dfs (int u, int la) {
    fa[u][0] = la, d[u] = d[la] + 1;
    for (int i = 1; (1 << i) <= d[u]; ++i)
        fa[u][i] = fa[fa[u][i - 1]][i - 1];
    for (int v : g[u]) if (v != la) dfs (v, u);
}
int lca (int x, int y) {
    if (d[x] < d[y]) swap (x, y);
    for (int i = 18; ~i; --i)
        if (d[fa[x][i]] >= d[y]) x = fa[x][i];
    if (x == y) return x;
    for (int i = 18; ~i; --i)
        if (fa[x][i] ^ fa[y][i]) x = fa[x][i], y = fa[y][i];
    return fa[x][0];
}
int run (int x, int o) {
    for (int i = 18; ~i; --i)
        if ((1 << i) <= o) o -= (1 << i), x = fa[x][i];
    return x;
}
void jump (int &x, int &y, int t) {
    int dx = d[x] - d[t], dy = d[y] - d[t], xx = x;
    x = dx > k ? run (x, k) : run (y, dy - (k - dx));
    y = dy > k ? run (y, k) : run (xx, dx - (k - dy));
}
signed main() {
    read (n), read (k), read (r); int tot = n;
    for (int i = 1, u, v; i < n; ++i) {
        read (u), read (v);
        if (k & 1) {
            g[u].pb (++tot), g[tot].pb (u);
            g[v].pb (tot), g[tot].pb (v);
        } else g[u].pb (v), g[v].pb (u);
    }
    n = tot; if (k & 1) k <<= 1; k >>= 1;
    for (int i = 1; i <= r; ++i) read (a[i]);
    for (int i = 1; i <= n; ++i) f[i] = i;
    bfs (), dfs (1, 0);
    int q, x, y; read (q);
    while (q--) {
        read (x), read (y); int t = lca (x, y);
        if (d[x] + d[y] - 2 * d[t] <= k * 2) puts ("YES");
        else jump (x, y, t), puts (get (x) == get (y) ? "YES" : "NO");
    }
    return 0;
}

G

。。。

原文地址:https://www.cnblogs.com/whx666/p/621-div12.html