zoukankan      html  css  js  c++  java
  • BZOJ

    题意:

      给出一棵树。两种操作,第一种是询问点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
  • 相关阅读:
    bootstrap-table 数据表格行内修改
    java文件上传(单文件 多文件)与删除
    bootstrap-table之通用方法( 时间控件,导出,动态下拉框, 表单验证 ,选中与获取信息)
    bootstrap-table 大量字段整体表单上传之时间处理
    Java实习问题记录
    Playbook剧本初识
    自动化运维工具-Ansible基础
    性能优化概述
    Rewrite基本概述
    Nginx常见问题
  • 原文地址:https://www.cnblogs.com/Pneuis/p/9236554.html
Copyright © 2011-2022 走看看