• 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。

    Solution

    这道题有两种方法:

    • 树链剖分
    • DFS预处理异或前缀和

    一.树链剖分
    就是一个板子,直接把边权化为点权即可做.
    时间复杂度 O(mlogn)

    二. DFS处理异或处理前缀和

    首先要知道异或的基本性质 :

    [{({x}igoplus{y})}igoplus{y}=x ]

    然后这道题,我们将边权转化为点权。
    每次需要的是从 LCA(x,y)-x 以及 LCA(x,y)-y ;
    然后我们记录根节点到每一个点的异或前缀和.
    此时:

    [Ans={Xorsum_{x}}igoplus{Xorsum_{y}}igoplus{Xorsum_{LCA(x,y)}} ]

    然后我们直接 DFS 预处理,然后 O(1)查询即可.
    时间复杂度O(n+m)

    代码

    一.树链剖分

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=200008;
    int n,m;
    struct sj{
    	int to;
    	int next;
    	int w;
    }a[maxn];
    int size,head[maxn];
    
    void add(int x,int y,int z)
    {
    	a[++size].to=y;
    	a[size].w=z;
    	a[size].next=head[x];
    	head[x]=size;
    }
    int dep[maxn],fa[maxn];
    int top[maxn],son[maxn];
    int siz[maxn];
    
    void dfs(int x)
    {
        siz[x]=1;
        for(int i=head[x];i;i=a[i].next)
        {
            int tt=a[i].to;
            if(!siz[tt])
            {
                dep[tt]=dep[x]+1;
                fa[tt]=x;
                dfs(tt);
                siz[x]+=siz[tt];
                if(siz[tt]>siz[a[son[x]].to])
                son[x]=i;
            }
        }
    }
    
    int id[maxn],num,c[maxn];
    void dfs1(int x,int y)
    {
    	top[x]=y;
    	if(son[x])
    	{
    		int tt=a[son[x]].to;
    		c[++num]=a[son[x]].w;
    		id[a[son[x]].to]=num;
    		dfs1(tt,y);
    	}
    	for(int i=head[x];i;i=a[i].next)
    	{
    		int tt=a[i].to;
    		if(!top[tt])
    		if(i!=son[x])
    		{
    			c[++num]=a[i].w;
    			id[a[i].to]=num;
    			dfs1(tt,tt);
    		}
    	}
    }
    
    int sgm[maxn*4];
    void build(int node,int l,int r)
    {
    	if(l==r)
    	{sgm[node]=c[l];return;}
    	int mid=(l+r)/2;
    	build(node*2,l,mid);
    	build(node*2+1,mid+1,r);
    	sgm[node]=(sgm[node*2]^sgm[node*2+1]);
    }
    
    int query(int node,int l,int r,int L,int R)
    {
    	if(l>R||r<L)return 0;
    	if(l>=L&&r<=R)return sgm[node];
    	int mid=(l+r)/2;
    	return (query(node*2,l,mid,L,R))^(query(node*2+1,mid+1,r,L,R));
    }
    
    int check(int x,int y)
    {
        int ans=0;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            ans^=query(1,1,n,id[top[x]],id[x]);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y])swap(x,y);
        ans^=query(1,1,n,id[x]+1,id[y]);
        return ans;
    }
    
    int main()
    {
    	cin>>n;
    	for(int i=1;i<n;i++)
    	{
    		int x,y,z;
    		scanf("%d%d%d",&x,&y,&z);
    		add(x,y,z); add(y,x,z);
    	}
    	dfs(1); dfs1(1,1);
    	build(1,1,n);
    	cin>>m;
    	while(m--)
    	{
    		int x,y; 
    		scanf("%d%d",&x,&y);
    		cout<<check(x,y)<<endl;
    	}
    }
    

    **二.DFS预处理** ```cpp #include #include #include #include using namespace std; typedef long long ll; int len,last[1001000],sum[1010000],k,p[35]; struct node { int to,next,w; }a[1010000]; void add(int a1,int a2,int a3) { len++; a[len].to=a2; a[len].w=a3; a[len].next=last[a1]; last[a1]=len; } void dfs(int x,int father) { for(int i=last[x];i;i=a[i].next) { int to=a[i].to; if(to==father) continue; sum[to]=sum[x]^(a[i].w); dfs(to,x); } } int main() { int n,x,y,z,ans=0; cin>>n; for(int i=1;i>m; for(int i=1;i<=m;i++) scanf("%d%d",&x,&y),printf("%d ",sum[x]^sum[y]); } ```
  • 相关阅读:
    MyBatis框架浅析之 缓存
    MyBatis框架浅析之 Mapper.xml 映射文件
    MyBatis框架浅析之 XML配置文件
    MySQL安装
    C语言内存分配
    二叉树性质
    pycharm使用anaconda的python环境
    linux删除文件夹、文件名字转码、java转码、json字符报错、查看当前系统编码、传代码至git
    java 性能优化
    java 建maplist放case center合并
  • 原文地址:https://www.cnblogs.com/Kv-Stalin/p/9240764.html
Copyright © 2020-2023  润新知