BZOJ - 2819 Nim

题意:

  给出一棵树。两种操作,第一种是询问点u,v路径上的异或和,另一种是改一个点的值。

题解:

  维护每个点到根节点的异或和。那么两个点之间的异或和就是两个点分别到根节点的异或和相异或,再异或上他们LCA节点的权值。

  对于每次更改,只会影响他的子树到根节点的异或和。所以可以维护DFS序,每次修改一个点的值时,用树状数组差分的形式修改in[]和out[]区间内的点。

#include <bits/stdc++.h>
using namespace std;
const int N = 5e5+10;
char s[2];
int n, q;
int u, v, tot, cnt;
int w[N];
int tre[N];
int in[N], out[N];
int depth[N];
int fa[20][N];
int head[N], to[N<<1], nxt[N<<1];
void add(int pos, int v) {
    while(pos <= n) {
        tre[pos] ^= v;
        pos += pos&(-pos);
    }
}
int sum(int pos) {
    int res = 0;
    while(pos > 0) {
        res ^= tre[pos];
        pos -= pos&(-pos);
    }
    return res;
}
void dfs(int u, int pre, int d) {
    in[u] = ++cnt;
    depth[u] = d;
    fa[0][u] = pre;
    add(cnt, w[u]);
    for(int i = head[u]; ~i; i = nxt[i]) {
        if(to[i] == pre) continue;
        dfs(to[i], u, d+1);
    }
    out[u] = cnt;
    add(cnt+1, w[u]);
}
int lca(int u, int v) {
    if(depth[u] < depth[v]) swap(u, v);
    int state = depth[u]-depth[v];
    for(int i = 19; i >= 0; i--) if((1<<i) & state) {
        u = fa[i][u];
    }
    if(u == v) return u;
    for(int i = 19; i >= 0; i--) if(fa[i][u] != fa[i][v]) {
        u = fa[i][u];
        v = fa[i][v];
    }
    return fa[0][u];
} 
int main() {
    scanf("%d", &n);
    memset(head, -1, sizeof(int)*(n+2));
    for(int i = 1; i <= n; i++) scanf("%d", &w[i]);
    for(int i = 1; i < n; i++) {
        scanf("%d%d", &u, &v);
        to[++tot] = v; nxt[tot] = head[u]; head[u] = tot;
        to[++tot] = u; nxt[tot] = head[v]; head[v] = tot;
    }
    dfs(1, 0, 0);
    for(int i = 0; i < 19; i++)
    for(int j = 1; j <= n; j++)
    fa[i+1][j] = fa[i][fa[i][j]];
    scanf("%d", &q);
    while(q--) {
        scanf("%s%d%d", s, &u, &v);
        if(s[0] == 'Q') {
            if(sum(in[u])^sum(in[v])^w[lca(u, v)]) puts("Yes");
            else puts("No");
        }
        else {
            add(in[u], w[u]^v);
            add(out[u]+1, w[u]^v);
            w[u] = v;
        }
    } 
} 
View Code

 

posted @ 2018-06-27 23:26  Pneuis  阅读(170)  评论(0编辑  收藏  举报