「解题报告」[省选联考 2021 A/B 卷] 宝石
简单题。
考虑只往上跳怎么做。由于当收集了某个宝石之后,后面的路径就是固定的了,于是我们预处理出每个点的下一个能够收集宝石的地方在哪里,然后倍增即可。
现在有上有下,那么树剖一下,对每条链预处理出倍增数组,然后每次在一条链上倍增即可。
今天模拟赛的 T1 刚好和这题做法一模一样 我做题的时机挺神奇(
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200005;
int n, m, c, q;
int p[MAXN], np[MAXN];
int w[MAXN];
struct Graph {
vector<int> e[MAXN];
void add(int u, int v) {
e[u].push_back(v);
}
int fa[MAXN], dep[MAXN], siz[MAXN], son[MAXN];
int top[MAXN], dfn[MAXN], dcnt, idf[MAXN];
int f[MAXN][22], g[MAXN][22];
void dfs1(int u, int pre) {
fa[u] = pre, dep[u] = dep[pre] + 1, siz[u] = 1;
for (int v : e[u]) if (v != pre) {
dfs1(v, u);
siz[u] += siz[v];
if (siz[v] > siz[son[u]]) son[u] = v;
}
}
void dfs2(int u, int pre, int t) {
top[u] = t, dfn[u] = ++dcnt, idf[dcnt] = u;
if (son[u]) dfs2(son[u], u, t);
for (int v : e[u]) if (v != pre && v != son[u]) {
dfs2(v, u, v);
}
}
vector<int> pos[MAXN];
void decomposition() {
dfs1(1, 0), dfs2(1, 0, 1);
for (int i = 1; i <= n; i++) {
pos[w[i]].push_back(dfn[i]);
}
for (int i = 1; i <= c; i++) {
sort(pos[i].begin(), pos[i].end());
}
for (int i = 1; i <= n; i++) {
int nc = p[np[w[i]] + 1];
auto nxt = lower_bound(pos[nc].begin(), pos[nc].end(), dfn[i]);
if (nxt != pos[nc].begin()) {
f[i][0] = idf[*prev(nxt)];
}
nxt = upper_bound(pos[nc].begin(), pos[nc].end(), dfn[i]);
if (nxt != pos[nc].end()) {
g[i][0] = idf[*nxt];
}
}
for (int j = 1; j <= 20; j++) {
for (int i = 1; i <= n; i++) {
f[i][j] = f[f[i][j - 1]][j - 1];
g[i][j] = g[g[i][j - 1]][j - 1];
}
}
}
struct Seg {
int l, r;
};
int query(int u, int v) {
int x = u, y = v;
vector<Seg> up, down;
while (top[x] != top[y]) {
if (dep[top[x]] > dep[top[y]]) {
up.push_back({dfn[top[x]], dfn[x]});
x = fa[top[x]];
} else {
down.push_back({dfn[top[y]], dfn[y]});
y = fa[top[y]];
}
}
if (dep[x] > dep[y]) up.push_back({dfn[y], dfn[x]});
else down.push_back({dfn[x], dfn[y]});
reverse(down.begin(), down.end());
int c = 1;
for (auto s : up) {
auto nxt = upper_bound(pos[p[c]].begin(), pos[p[c]].end(), s.r);
if (nxt != pos[p[c]].begin() && *prev(nxt) >= s.l) {
int t = idf[*prev(nxt)];
for (int i = 20; i >= 0; i--) if (f[t][i] && dfn[f[t][i]] >= s.l)
t = f[t][i];
c = np[w[t]] + 1;
}
}
for (auto s : down) {
auto nxt = lower_bound(pos[p[c]].begin(), pos[p[c]].end(), s.l);
if (nxt != pos[p[c]].end() && *nxt <= s.r) {
int t = idf[*nxt];
for (int i = 20; i >= 0; i--) if (g[t][i] && dfn[g[t][i]] <= s.r)
t = g[t][i];
c = np[w[t]] + 1;
}
}
return c - 1;
}
} g;
int main() {
scanf("%d%d%d", &n, &m, &c);
for (int i = 1; i <= c; i++) {
scanf("%d", &p[i]);
np[p[i]] = i;
}
for (int i = 1; i <= n; i++) {
scanf("%d", &w[i]);
}
for (int i = 1; i < n; i++) {
int u, v; scanf("%d%d", &u, &v);
g.add(u, v);
g.add(v, u);
}
g.decomposition();
scanf("%d", &q);
while (q--) {
int u, v; scanf("%d%d", &u, &v);
printf("%d\n", g.query(u, v));
}
return 0;
}