P10799 题解
Register_int · · 题解
先考虑不在树上咋做。先给序列排序,然后一个一个判是否有
如果不满足要求的话,那么对于所有
回到原题,查询只要先判路径长度再暴力跳即可。这部分是简单的,压力给到链异或单点查询。
容易发现,每次修改都能拆成四次到根链的修改。具体地,设
AC 代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
vector<int> g[MAXN];
int n, a[MAXN], dep[MAXN], fa[20][MAXN];
int c[MAXN], in[MAXN], out[MAXN], id;
void init(int u, int f) {
fa[0][u] = f, dep[u] = dep[f] + 1, in[u] = ++id, a[f] ^= a[u];
for (int i = 1; i <= __lg(dep[u]); i++) fa[i][u] = fa[i - 1][fa[i - 1][u]];
for (int v : g[u]) if (v != f) init(v, u); out[u] = id;
}
inline
void add(int u, int x) {
for (int i = in[u]; i <= n; i += i & -i) c[i] ^= x;
}
inline
int ask(int u) {
int res = 0;
for (int i = out[u]; i; i &= i - 1) res ^= c[i];
for (int i = in[u] - 1; i; i &= i - 1) res ^= c[i];
return res;
}
inline
int lca(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
for (; dep[u] > dep[v]; u = fa[__lg(dep[u] - dep[v])][u]);
if (u == v) return u;
for (int i = __lg(dep[u]); ~i; i--) {
if (fa[i][u] != fa[i][v]) u = fa[i][u], v = fa[i][v];
}
return fa[0][u];
}
inline
vector<int> get(int u, int v) {
vector<int> d;
if (dep[u] < dep[v]) swap(u, v);
for (; dep[u] > dep[v]; d.emplace_back(ask(u)), u = fa[0][u]);
for (; u != v; ) {
d.emplace_back(ask(u)), u = fa[0][u];
d.emplace_back(ask(v)), v = fa[0][v];
}
return d.emplace_back(ask(u)), d;
}
inline
bool check(vector<int> d) {
sort(d.begin(), d.end()); int m = d.size();
for (int i = 1; i < m - 1; i++) {
if (d[i - 1] > d[i + 1] - d[i]) return 1;
}
return 0;
}
inline
void modify(int u, int v, int w) {
int k = lca(u, v);
add(u, w), add(v, w), add(k, w);
if (fa[0][k]) add(fa[0][k], w);
}
inline
bool query(int u, int v) {
int k = lca(u, v);
if (dep[u] + dep[v] - 2 * dep[k] + 1 > 46) return 1;
else return check(get(u, v));
}
int m;
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1, u, v; i < n; i++) {
scanf("%d%d", &u, &v);
g[u].emplace_back(v), g[v].emplace_back(u);
}
init(1, 0);
for (int i = 1; i <= n; i++) add(i, a[i]);
for (int opt, u, v, w; m--;) {
scanf("%d%d%d", &opt, &u, &v);
if (opt == 1) scanf("%d", &w), modify(u, v, w);
else printf("%d", query(u, v));
}
}