题目描述

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

在生活中…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}\bigoplus{y})}\bigoplus{y}=x
\]

然后这道题,我们将边权转化为点权。

每次需要的是从 LCA(x,y)-x 以及 LCA(x,y)-y ;

然后我们记录根节点到每一个点的异或前缀和.

此时:

\[Ans={Xorsum_{x}}\bigoplus{Xorsum_{y}}\bigoplus{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

P2420 让我们异或吧 (树链剖分,异或前缀和)的更多相关文章

  1. BZOJ 4568 [Scoi2016]幸运数字(树链剖分 + 异或线性基)

    题目链接  BZOJ 4568 考虑树链剖分+线段树维护每一段区域的异或线性基 对于每个询问,求出该点集的异或线性基.然后求一下这个线性基里面能异或出的最大值即可. #include <bits ...

  2. P2420 让我们异或吧(树链剖分)

    题目描述 异或是一种神奇的运算,大部分人把它总结成不进位加法. 在生活中-xor运算也很常见.比如,对于一个问题的回答,是为1,否为0.那么: (A是否是男生 )xor( B是否是男生)=A和B是否能 ...

  3. 树链剖分好(du)题(liu)选做

    1.luogu P4315 月下"毛景树" 题目链接 前言: 这大概是本蒟蒻A掉的题里面码量最大的一道题了.我自认为码风比较紧凑,但还是写了175行. 从下午2点多调到晚上8点.中 ...

  4. 【BZOJ-4568】幸运数字 树链剖分 + 线性基合并

    4568: [Scoi2016]幸运数字 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 238  Solved: 113[Submit][Status ...

  5. HDU 4897 Little Devil I(树链剖分)(2014 Multi-University Training Contest 4)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4897 Problem Description There is an old country and ...

  6. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  7. [BZOJ - 2819] Nim 【树链剖分 / DFS序】

    题目链接: BZOJ - 2819 题目分析 我们知道,单纯的 Nim 的必胜状态是,各堆石子的数量异或和不为 0 .那么这道题其实就是要求求出树上的两点之间的路径的异或和.要求支持单点修改. 方法一 ...

  8. HDU 5274 Dylans loves tree(树链剖分)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5274 [题目大意] 给出一棵树,每个点有一个权值,权值可修改,且大于等于0,询问链上出现次数为奇数 ...

  9. 从lca到树链剖分 bestcoder round#45 1003

    bestcoder round#45 1003 题,给定两个点,要我们求这两个点的树上路径所经过的点的权值是否出现过奇数次.如果是一般人,那么就是用lca求树上路径,然后判断是否出现过奇数次(用异或) ...

随机推荐

  1. 跑edgebox

    这是edge的作者的代码:https://github.com/pdollar/edges 这是matlab写的,还需要装Matlab Image Processing Toolbox和Piotr's ...

  2. CentOS为用户增加root权限

    1.修改 /etc/sudoers vi /etc/sudoers 在下边增加一行内容 root    ALL=(ALL)     ALLusername   ALL=(ALL)     ALL 2. ...

  3. Java执行系统命令工具类(JDK自带功能)

    CommandUtil.java package utils; import java.io.ByteArrayOutputStream; import java.io.IOException; im ...

  4. python 列表 字典转json

    一.Dictionary 转为JSON 将dict转为JSON,这里利用包json import jsonaItem = {}aItem["id"] = "2203&qu ...

  5. oracle 数据导到 sql server

    方法一: navicate:用法比较简单,选择工具-数据传输就可以了.目前测试了下暂时没遇到什么问题. 方法二: Microsoft SQL Server Migration Assistant 8. ...

  6. iOS 解决ipv6问题

    解决ipv6的方法有很多种,由于现在国内的网络运营商还在使用ipv4的网络环境,所以appstore应用不可能大范围去修改自己的服务器, 而且国内的云服务器几乎没有ipv6地址. 这里附上苹果开发平台 ...

  7. OpenCV3.42+VS2017配置+模块计算机类型“X86”与目标计算机类型“x64”冲突”的问题解决

    目录 OpenCV3.42+VS2017配置 Visual Studio 2017 第三方依赖设置,附加依赖项和附加库目录 "fatal error LNK1112: 模块计算机类型&quo ...

  8. MATLAB编程技巧

    [摘要] MATLAB是一种科学计算语言,和C.Fortran等高级语言相类似,能方便的实现程序控制.以下介绍一点matlab编程的技巧. 嵌套计算 程序执行的速度取决于调用的子程序的个数和算法实现. ...

  9. 【HIHOCODER 1142】 三分·三分求极值

    描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d. 输入 第1行:5个整数a,b,c,x,y.前三个数构成抛物 ...

  10. HDU - 5884 Sort (二分答案+贪心)

    有n个数字,你需要把这n个数字合成一个数字,每次只能把k个数字合并成一个,花费为这k个数字的和. 给一个最大花费,问不超过这个最大花费的情况下,k的最小值. Sample Input 1 5 25 1 ...