zoukankan      html  css  js  c++  java
  • 洛谷P2420 让我们异或吧(树链剖分)

    题目描述
    异或是一种神奇的运算,大部分人把它总结成不进位加法.

    在生活中…xor运算也很常见。比如,对于一个问题的回答,是为1,否为0.那么:

    (A是否是男生 )xor( B是否是男生)=A和B是否能够成为情侣

    好了,现在我们来制造和处理一些复杂的情况。比如我们将给出一颗树,它很高兴自己有N个结点。树的每条边上有一个权值。我们要进行M次询问,对于每次询问,我们想知道某两点之间的路径上所有边权的异或值。

    输入输出格式
    输入格式:
    输入文件第一行包含一个整数N,表示这颗开心的树拥有的结点数,以下有N-1行,描述这些边,每行有3个数,u,v,w,表示u和v之间有一条权值为w的边。接下来一行有一个整数M,表示询问数。之后的M行,每行两个数u,v,表示询问这两个点之间的路径上的权值异或值。

    输出格式:
    输出M行,每行一个整数,表示异或值

    输入输出样例
    输入样例#1:
    5
    1 4 9644
    2 5 15004
    3 1 14635
    5 3 9684
    3
    2 4
    5 4
    1 1
    输出样例#1:
    975
    14675
    0
    说明
    对于40%的数据,有1 ≤ N,M ≤ 3000;

    对于100%的数据,有1 ≤ N ,M≤ 100000。

    题解:首先异或和加法一样zici区间加,并且求的是路径异或和,所以自然可以想到树剖维护。好吧,其实我一开始的思路是树形dp+LCA瞎搞搞的,但是因为把边权看成了点权所以果断选择了树剖。边权的树剖怎么写,其实和点也没有什么区别,就是传递的时候多带一个边值罢了。

    代码如下:

    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define lson root<<1
    #define rson root<<1|1
    using namespace std;
    
    struct node
    {
        int l,r,lazy,sum;
    }tr[400040];
    int w[100010],son[100010],fa[100010],id[100010],deep[100010],size[100010],top[100010],vv[100010],cnt=0;
    vector<int> g[100010],v[100010];
    
    void push_up(int root)
    {
        tr[root].sum=tr[lson].sum^tr[rson].sum;
    }
    
    void build(int root,int l,int r)
    {
        if(l==r)
        {
            tr[root].l=l;
            tr[root].r=r;
            tr[root].sum=w[l];
            return ;
        }
        tr[root].l=l;
        tr[root].r=r;
        int mid=(l+r)>>1;
        build(lson,l,mid);
        build(rson,mid+1,r);
        push_up(root);
    }
    
    int query(int root,int l,int r)
    {
        if(l>r)
        {
            return 0;
        }
        if(l==tr[root].l&&r==tr[root].r)
        {
            return tr[root].sum;
        }
        int mid=(tr[root].l+tr[root].r)>>1;
        if(l>mid)
        {
            return query(rson,l,r);
        }
        else
        {
            if(r<=mid)
            {
                return query(lson,l,r);
            }
        }
        return query(lson,l,mid)^query(rson,mid+1,r);
    }
    
    void dfs1(int now,int f,int dep)
    {
        deep[now]=dep;
        fa[now]=f;
        size[now]=1;
        int maxson=-1;
        for(int i=0;i<g[now].size();i++)
        {
            if(g[now][i]==f)
            {
                continue;
            }
            dfs1(g[now][i],now,dep+1);
            size[now]+=size[g[now][i]];
            if(size[g[now][i]]>maxson)
            {
                maxson=size[g[now][i]];
                son[now]=g[now][i];
                vv[now]=v[now][i];
            }
        }
    }
    
    void dfs2(int now,int topf,int val)
    {
        id[now]=++cnt;
        w[cnt]=val;
        top[now]=topf;
        if(!son[now])
        {
            return ;
        }
        dfs2(son[now],topf,vv[now]);
        for(int i=0;i<g[now].size();i++)
        {
            if(g[now][i]==fa[now]||g[now][i]==son[now])
            {
                continue;
            }
            dfs2(g[now][i],g[now][i],v[now][i]);
        }
    }
    
    void path_sum(int x,int y)
    {
        int ans=0;
        while(top[x]!=top[y])
        {
            if(deep[top[x]]<deep[top[y]])
            {
                swap(x,y);
            }
            ans^=query(1,id[top[x]]+1,id[x]);
            ans^=w[id[top[x]]];
            x=fa[top[x]];
        }
        if(deep[x]>deep[y])
        {
            swap(x,y);
        }
        ans^=query(1,id[x]+1,id[y]);
        printf("%d
    ",ans);
    }
    
    int main()
    {
        int n,m;
        scanf("%d",&n);
        for(int i=1;i<=n-1;i++)
        {
            int from,to,ww;
            scanf("%d%d%d",&from,&to,&ww);
            g[from].push_back(to);
            v[from].push_back(ww);
            g[to].push_back(from);
            v[to].push_back(ww);
        }
        dfs1(1,0,1);
        dfs2(1,1,0);
        build(1,1,n);
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            int from,to;
            scanf("%d%d",&from,&to);
            path_sum(from,to);
        }
    }
  • 相关阅读:
    正则表达式的贪婪匹配(.*)和非贪婪匹配(.*?)
    jQuery + css 公告从左往右滚动
    C# process 使用方法
    存储过程与SQL的结合使用
    img标签的方方面面
    kibana 5.0.0-alpha5 安装
    es5.0 v5.0.0-alpha 编译安装
    奇怪的hosts文件
    阿里云 api 的文档拼写错误
    centos 7 systemd docker http proxy
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/8645386.html
Copyright © 2011-2022 走看看