Dylans loves tree

\(trick\)

如果有3个点,权值都为0,尽管异或为0,但0是出现了奇数次,应该输出0....

\(code\)

树剖模板
const int N = 100005;

int n, q, tot, cnt;
int head[N], pa[N], dep[N], sz[N], son[N], top[N], id[N], rk[N];

struct node { int to, next; } e[N * 2];

void Inite() {
    cnt = tot = 0;
    mem(head, -1);
}

void addedge(int u, int v) {
    e[tot].to = v, e[tot].next = head[u], head[u] = tot++;
}

void DFS1(int u, int p, int deep) {
    pa[u] = p;
    sz[u] = 1;
    dep[u] = deep;
    for (int i = head[u]; ~i; i = e[i].next) if (e[i].to != p) {
        int v = e[i].to;
        DFS1(v, u, deep + 1);
        sz[u] += sz[v];
        if (son[u] == -1 || sz[v] > sz[son[u]]) son[u] = v;
    }
}

void DFS2(int u, int st) {
    top[u] = st;
    id[u] = ++cnt;
    rk[cnt] = u;
    if (son[u] == -1) return;
    DFS2(son[u], st);
    for (int i = head[u]; ~i; i = e[i].next) if (e[i].to != son[u] && e[i].to != pa[u]) DFS2(e[i].to, e[i].to);
}

int a[N], sum[4 * N];

void Pushup(int root) {
    sum[root] = sum[lson] ^ sum[rson];
}

void Build(int l, int r, int root) {
    if (l == r) {
        sum[root] = a[rk[++cnt]] + 1;
        return;
    }
    int mid = (l + r) >> 1;
    Build(l, mid, lson);
    Build(mid + 1, r, rson);
    Pushup(root);
}

void Update(int l, int r, int root, int pos, int x) {
    if (l == r) {
        sum[root] = x;
        return;
    }
    int mid = (l + r) >> 1;
    if (pos <= mid) Update(l, mid, lson, pos, x);
    else Update(mid + 1, r, rson, pos, x);
    Pushup(root);
}

int Query(int l, int r, int root, int L, int R) {
    if (l > R || r < L) return 0;
    if (L <= l && r <= R) return sum[root];
    int mid = (l + r) >> 1;
    int ans = 0;
    ans ^= Query(l, mid, lson, L, R);
    ans ^= Query(mid + 1, r, rson, L, R);
    return ans;
}

int check(int u, int v) {
    int ans = 0;
    int pu = top[u], pv = top[v];

    while(pu != pv) {
        if (dep[pu] > dep[pv]) {
            ans ^= Query(1, n, 1, id[pu], id[u]);
            u = pa[pu];
        }
        else {
            ans ^= Query(1, n, 1, id[pv], id[v]);
            v = pa[pv];
        }
        pu = top[u], pv = top[v];
    }

    if (id[u] <= id[v]) ans ^= Query(1, n, 1, id[u], id[v]);
    else ans ^= Query(1, n, 1, id[v], id[u]);

    return ans;
}

int main()
{
    BEGIN() {
        sc(n), sc(q);

        Inite();
        Rep(i, 2, n) {
            int u, v;
            sc(u), sc(v);
            addedge(u, v);
            addedge(v, u);
        }
        Rep(i, 1, n) sc(a[i]);

        mem(son, -1);
        DFS1(1, 1, 0);
        DFS2(1, 1);

        cnt = 0;
        mem(sum, 0);
        Build(1, n, 1);

        while(q--) {
            int op;
            sc(op);
            if (op == 0) {
                int x, y;
                sc(x), sc(y);
                Update(1, n, 1, id[x], y + 1);
            }
            else {
                int u, v;
                sc(u), sc(v);
                pr(check(u, v) - 1);
            }
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zgglj-com/p/9822969.html

时间: 2024-10-16 10:35:56

Dylans loves tree的相关文章

AC日记——Dylans loves tree hdu 5274

Dylans loves tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1611    Accepted Submission(s): 388 Problem Description Dylans is given a tree with N nodes. All nodes have a value A[i] .Node

HDU5274 Dylans loves tree(树链剖分)很巧的点权更新

Dylans loves tree Accepts: 49 Submissions: 262 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) 问题描述 Dylans有一棵N个点的树.每个点有点权.树上节点标号为1∼N. 他得到了Q个询问,形式如下: ①0 x y:把第x个点的点权修改为y. ②1 x y:对于x∼y路径上的每一种点权,是否都出现偶数次? 保证每次询问的路径上最多只

HDU 5274 Dylans loves tree(LCA+dfs时间戳+成段更新 OR 树链剖分+单点更新)

Problem Description Dylans is given a tree with N nodes. All nodes have a value A[i].Nodes on tree is numbered by 1∼N. Then he is given Q questions like that: ①0 x y:change node x′s value to y ②1 x y:For all the value in the path from x to y,do they

hdu5274 Dylans loves tree LCA+线段树

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5274 在树上的询问和操作,每次修改单点值,询问两点之间出现次数为奇数的点权是什么,若没有输出-1.询问保证两点间至多只有一个数出现奇数次. 有一种经典的将树上的点转化成序列的方法,我们用dfs遍历这棵树,那么对于一个节点,他一点比他的子树即子节点先访问到,且当他的最后一个子节点的所有子树也都访问完时,这中间访问的节点一定都是他的子树.那么我们可以在访问时做一下记录,每个点首先被访问的clock,和结束时

BestCoder #45 1003 Dylans loves tree

problem 题意 给定一棵树,并给定在这棵树上的两种操作.一种操作是改变一个节点的权值,另外一个操作是对两个节点之间的路径上的权值进行统计,如果每个权值出现的次数都是偶数,输出-1,否则输出出现次数为奇数的权值(保证只有一个) 思路 这题是一个DFS序的模板题.首先想到,我们获得这棵树的DFS序,对于这个序列,我们可以去维护区间的异或和.由于是单点修改区间查询,可以用树状数组也可以直接写线段树.然后对于每个询问,我们查询出每个点到根的异或和(这里直接用DFS序中到根节点的异或和即可,因为如果

HDU5274 Dylans loves tree(树链剖分+异或)

传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5274 题意很简单,输入以后,查询的时候 0 x y,是把x点改成y. 1 x y,是查询[x,y]中,数字出现的次数是否都是偶数,出现奇数的数字<=1. 都是偶数的话,输出-1,有奇数的话,输出奇数的权值. 思路:这题也是一个裸题,但是这题的线段树维护的比较巧妙,因为一个数异或自己偶数次就是0,所以求一个区间异或和就行了.但是有个地方要注意,就是权值为0的话,异或自己,奇数次也是0.所以可以把所有的权

hdu 5273 Dylans loves sequence 逆序数简单递推

Dylans loves sequence Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5273 Description Dylans得到了N个数a[1]...a[N].有Q个问题,每个问题形如(L,R)他需要求出L−R这些数中的逆序对个数.更加正式地,他需要求出二元组(x,y)的个数,使得L≤x,y≤R且x<y且a[x]>a[y] Input 第一行有两个数N和Q

hdu 5272 Dylans loves numbers 水题

Dylans loves numbers Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5272 Description Dylans是谁?你可以在 UOJ 和 Codeforces上看到他.在BestCoder里,他有另外一个ID:s1451900.今天的题目都和他有关哦.Dylans得到了一个数N.他想知道N的二进制中有几组1.如果两个1之间有若干个(至少一个)0

HDU 5273 Dylans loves sequence(区间DP)

Dylans loves sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 114    Accepted Submission(s): 59 Problem Description Dylans is given N numbers a[1]....a[N] And there are Q questions. E