P8201
题外话,比赛时大家好像都在树剖,没见到几个写差分的((这题不会成了天天爱跑步 2.0 吧(
F2. 生活在树上(hard version)
题意:给定一棵树,点数为
关键词:前缀和,构造,树上差分。
参考难度:绿。
分析:首先异或构成一个 Abel 群,所以如果一个点在
考虑
图中红色路径是
于是我们发现,
于是问题就变成了
统计
时间复杂度为
(C++)
#include <array>
#include <vector>
#include <iostream>
const int maxn = 1000005;
const int maxw = 10000007;
int n, q;
std::array<std::vector<int>, maxn> e;
std::array<int, maxn> a, b, lca, ufs, rnk, anc, kk, cnt, fa, k, ans;
std::array<bool, maxn> vis;
std::array<std::vector<std::pair<int, int> >, maxn> qry, QQ;
std::array<std::pair<int, int>, maxn> Q;
std::array<int, maxw> bk;
void dfs2(const int u);
void dfs(const int u, const int f);
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cin >> n >> q;
for (int i = 1; i <= n; ++i) {
std::cin >> a[i];
rnk[ufs[i] = anc[i] = i] = 1;
}
for (int u, v, i = 1; i < n; ++i) {
std::cin >> u >> v;
e[u].push_back(v); e[v].push_back(u);
}
for (int i = 1, u, v; i <= q; ++i) {
std::cin >> u >> v >> kk[i];
qry[u].push_back(std::make_pair(v, i));
qry[v].push_back(std::make_pair(u, i));
Q[i] = std::make_pair(u, v);
}
dfs(1, 0);
for (int i = 1; i <= q; ++i) if ((k[i] = b[Q[i].first] ^ b[Q[i].second] ^ a[lca[i]] ^ kk[i]) < maxw) {
QQ[Q[i].first].push_back(std::make_pair(i, 1));
QQ[Q[i].second].push_back(std::make_pair(i, 1));
QQ[lca[i]].push_back(std::make_pair(i, -1));
QQ[fa[lca[i]]].push_back(std::make_pair(i, -1));
}
dfs2(1);
std::array<std::string, 2> prt{"nO\n", "yEs\n"};
for (int i = 1; i <= q; ++i) std::cout << prt[ans[i] > 0];
}
int find(int x) { return ufs[x] == x ? x : ufs[x] = find(ufs[x]); }
void dfs(const int u, const int f) {
b[u] = a[u] ^ b[f];
fa[u] = f;
for (auto v : e[u]) if (v != f) {
dfs(v, u);
int x = find(u), y = find(v);
if (rnk[x] > rnk[y]) std::swap(x, y);
anc[ufs[x] = y] = u;
if (rnk[x] == rnk[y]) ++rnk[y];
}
for (auto [v, i] : qry[u]) if (vis[v]) {
lca[i] = anc[find(v)];
}
vis[u] = true;
}
void dfs2(const int u) { // 这里是树上差分对应求结果的 dfs 函数
++bk[a[u]];
for (auto [i, w] : QQ[u]) {
ans[i] += w * bk[k[i]];
}
for (auto v : e[u]) if (v != fa[u]) {
dfs2(v);
}
--bk[a[u]];
}