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
。。。