Bzoj 2819 Nim
题意:
一棵大小为n(<=500000)的树,每个结点都有一个值,m次操作,1.询问u到v结点最短路上节点的异或值,如果不为0,输出Yes,否在输出No;2。更新某个节点的值
解题思路:
树上对于点的多次修改+链的多次询问
1.可以直接用树剖来处理,因为树剖就是处理链上问题
2.可以用dfs序,求树状数组(可是我不会dfs序…)
AC代码:
#include <bits/stdc++.h>
#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
using namespace std;
const int maxn = 5e5 + 10;
int n, q;
int tot, head[maxn];
int wson[maxn], top[maxn], d[maxn], siz[maxn], fa[maxn];
int cnt, id[maxn];
int w[maxn], wt[maxn << 2], a[maxn << 2];
struct Edge {
int to, nxt;
} edge[maxn << 1];
void add_edge(int u, int v) {
edge[++tot].nxt = head[u], head[u] = tot, edge[tot].to = v;
edge[++tot].nxt = head[v], head[v] = tot, edge[tot].to = u;
}
void dfs1(int u, int pre) {
siz[u] = 1;
for (int i = head[u]; i; i = edge[i].nxt) {
int v = edge[i].to;
if (v == pre) continue;
d[v] = d[u] + 1;
fa[v] = u;
dfs1(v, u);
siz[u] += siz[v];
if (siz[wson[u]] < siz[v]) wson[u] = v;
}
}
void dfs2(int u, int tp) {
//cout << u << " " << wson[u] << endl;
id[u] = ++cnt;
wt[cnt] = w[u];
top[u] = tp;
if(wson[u]) dfs2(wson[u], tp);
for (int i = head[u]; i; i = edge[i].nxt) {
int v = edge[i].to;
if (v == wson[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
//----
void pushup(int rt) {
a[rt] = a[rt << 1] ^ a[rt << 1 | 1];
}
void build(int lef, int rig, int rt) {
if (lef == rig) {
a[rt] = wt[lef];
return;
}
int mid = (lef + rig) >> 1;
build(lef, mid, rt << 1);
build(mid + 1, rig, rt << 1 | 1);
pushup(rt);
}
int query(int L, int R, int lef, int rig, int rt) {
int res = 0;
if (L <= lef && rig <= R) {
return a[rt];
}
int mid = (lef + rig) >> 1;
if (L <= mid) res ^= query(L, R, lef, mid, rt << 1);
if (mid < R) res ^= query(L, R, mid + 1, rig, rt << 1 | 1);
return res;
}
void update(int lef, int rig, int rt, int x, int val) {
if (lef == rig && lef == x) {
a[rt] = val;
return;
}
int mid = (lef + rig) >> 1;
if (x <= mid) update(lef, mid, rt << 1, x, val);
else update(mid + 1, rig, rt << 1 | 1, x, val);
pushup(rt);
}
int qrange(int x, int y) {
int ans = 0;
while (top[x] != top[y]) {
if (d[top[x]] < d[top[y]]) swap(x, y);
ans ^= query(id[top[x]], id[x], 1, n, 1);
x = fa[top[x]];
}
if (d[x] > d[y]) swap(x, y);
ans ^= query(id[x], id[y], 1, n, 1);
return ans;
}
void uppoint(int x, int k) {
update(1, n, 1, id[x], k);
}
int main() {
IOS;
cin >> n;
for (int i = 1; i <= n; i++)
cin >> w[i];
int u, v;
for (int i = 1; i < n; i++) {
cin >> u >> v;
add_edge(u, v);
}
dfs1(1, 0);
dfs2(1, 1);
build(1, n, 1);
cin >> q;
string oper;
while (q--) {
cin >> oper >> u >> v;
if (oper == "Q") {
if (qrange(u, v)) cout << "Yes" << endl;
else cout << "No" << endl;
}
else
uppoint(u, v);
}
//cout << qrange(5, 5) << endl;
}