自己想了一个做法,大概意思是判断 x→y 的路径上有没有对应的点,用了个树上前缀和,8pts WA,问问我这个程序(或者思路)有啥问题。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 5;
char c[MAXN], ch;
int cnt1[MAXN], cnt2[MAXN], d[MAXN], sz[MAXN], f[MAXN][18], n, m, x, y;
vector<int> G[MAXN];
void dfs(int x, int fa) {
// cout << "dfs visit (" << x << ")" << endl;
cnt1[x] = cnt1[fa] + (c[x] == 'G');
cnt2[x] = cnt2[fa] + (c[x] == 'H');
d[x] = d[fa] + 1; f[x][0] = fa;
for (int i = 1; (1 << i) <= d[x]; ++i) {
f[x][i] = f[f[x][i - 1]][i - 1];
}
for (auto v : G[x]) {
if (v == fa) continue;
// cout << "\t visit:" << v << endl;
dfs(v, x);
}
// cout << "visit end" << endl;
}
int lca(int x, int y) {
int dx = d[x], dy = d[y];
if (dx != dy) {
if (dx < dy) {
swap(dx, dy); swap(x, y);
}
int dd = dx - dy;
for (int i = 0; i <= __lg(n); ++i) {
if (dd & (1 << i)) x = f[x][i];
}
}
if (x == y) return x;
for (int i = __lg(n); i >= 0; --i) {
if (d[f[x][i]] <= 0) continue;
if (f[x][i] == f[y][i]) continue;
else x = f[x][i], y = f[y][i];
}
return f[x][0];
}
int main(void) {
ios::sync_with_stdio(false);
cin >> n >> m;
for (int i = 1; i <= n; ++i)
cin >> c[i];
for (int i = 1; i < n; ++i) {
cin >> x >> y;
G[x].push_back(y); G[y].push_back(x);
}
dfs(1, 0);
while (m--) {
cin >> x >> y >> ch;
int l = lca(x, y);
if (ch == 'G')
if (cnt1[x] - cnt1[l - 1] + cnt1[y] - cnt1[l] > 0)
cout << 1;
else
cout << 0;
else
if (cnt2[x] - cnt2[l - 1] + cnt2[y] - cnt2[l] > 0)
cout << 1;
else
cout << 0;
}
return 0;
}