点分治
板子: 给定一棵有 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"; } }}