点分治

板子: 给定一棵有 n 个点的树,m 次询问树上距离为 k 的点对是否存在。(n = 1e4, m = 100)

const int N = 1e4 + 5;
vector<pair<int, int>> adj[N];
int n, m;
vector<int> siz(N);
vector<i64> dis(N);
int q[105], ans[105];
bitset<100000000> has;
int find_root(int rt) {
auto dfs = [&](auto self, int u, int fa) -> void {
siz[u] = 1;
for (auto [v, w] : adj[u]) {
if (v == fa) continue;
self(self, v, u);
siz[u] += siz[v];
}
};
dfs(dfs, rt, 0);
int cen = 0;
auto DFS = [&](auto self, int u, int fa) -> void {
int mx = siz[rt] - siz[u];
for (auto [v, w] : adj[u]) {
if (v == fa) continue;
self(self, v, u);
mx = max(mx, siz[v]);
}
if (mx <= siz[rt] / 2) {
cen = u;
}
};
DFS(DFS, rt, 0);
return cen;
};
bool check() {
auto dfs = [&](auto self, int rt) -> void {
queue<int> que;
has[0] = 1;
que.emplace(0);
auto DFS = [&](auto self, int u, int fa, i64 d) -> void {
dis[u] = d;
for (int i = 1; i <= m; i++) {
if (q[i] >= d && q[i] - d <= 100000000 && has[q[i] - d]) {
ans[i] = 1;
}
}
for (auto [v, w] : adj[u]) {
if (v == fa) continue;
self(self, v, u, d + w);
}
};
auto add = [&](auto self, int u, int fa) -> void {
has[dis[u]] = 1;
que.emplace(dis[u]);
for (auto [v, w] : adj[u]) {
if (v == fa) continue;
self(self, v, u);
}
};
for (auto [v, w] : adj[rt]) {
DFS(DFS, v, rt, w);
add(add, v, rt);
}
while (!que.empty()) {
has[que.front()] = 0;
que.pop();
}
for (auto [v, w] : adj[rt]) {
adj[v].erase(find(adj[v].begin(), adj[v].end(), make_pair(rt, w)));
int cen = find_root(v);
self(self, cen);
adj[v].emplace_back(rt, w);
}
};
dfs(dfs, find_root(1));
return ans;
}
void solve() {
cin >> n >> m;
for (int i = 1; i < n; i++) {
int a, b, c;
cin >> a >> b >> c;
adj[a].emplace_back(b, c);
adj[b].emplace_back(a, c);
}
for (int i = 1; i <= m; i++) {
cin >> q[i];
}
check();
for (int i = 1; i <= m; i++) {
if (ans[i]) {
cout << "AYE\n";
} else {
cout << "NAY\n";
}
}
}