让我们异或吧

题目描述

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

在生活中…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。

这题其实很简单
比如说要查询u和v的xor
设tmp为u和v的lca(最近公共祖先)
dis[x]表示x到根的xor
xor有一个性质:x ^ y ^ y = x
就是说将一个数xor两遍另一个数还是那个数
因为dis[u]其中有一部分是dis[tmp],把dis[tmp]异或掉就得到u到tmp的xor
那就将dis[u] ^ dis[tmp]再异或 dis[v] ^ dis[tmp]就得到答案了

#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 100000 + 10;
int n,m,r,p,dis[maxn],dep[maxn],father[maxn][18];
vector<pair<int,int> > edges[maxn];
inline void dfs(int now,int f,int Xor) {  //dfs预处理
    dis[now] = Xor;
    for (size_t i = 0;i < edges[now].size();i++)
        if (edges[now][i].first != f) {
            dep[edges[now][i].first] = dep[now]+1;
            father[edges[now][i].first][0] = now;
            dfs(edges[now][i].first,now,Xor^edges[now][i].second);
        }
}
inline void init() {  //倍增
    for (int j = 1;j < 18;j++)
        for (int i = 1;i <= n;i++) father[i][j] = father[father[i][j-1]][j-1];
}
inline int lca(int a,int b) {  //求lca
    if (dep[a] < dep[b]) swap(a,b);
    for (int i = 0;i < 18;i++)
        if ((1<<i)&dep[a]-dep[b]) a = father[a][i];  //让深的点往上走
    if (a == b) return a;  //走到同一点
    for (int i = 18;i >= 0;i--)
        if (father[a][i] != father[b][i]) {  //两个一起往上走
            a = father[a][i];
            b = father[b][i];
        }
    return father[a][0];
}
int main() {
    scanf("%d",&n);
    for (int i = 1,u,v,w;i < n;i++) {
        scanf("%d%d%d",&u,&v,&w);
        edges[u].push_back(make_pair(v,w));
        edges[v].push_back(make_pair(u,w));
    }
    dfs(1,1,1);
    init();
    scanf("%d",&m);
    for (int i = 1,u,v;i <= m;i++) {
        scanf("%d%d",&u,&v);
        int tmp = lca(u,v);
        printf("%d\n",(dis[u]^dis[tmp])^(dis[v]^dis[tmp]));
    }
    return 0;
}

  

xor还满足结合律和交换律
我们将(dis[u]^dis[tmp])^(dis[v]^dis[tmp])打开
得到dis[u]^dis[v]^dis[tmp]^dis[tmp]
那么异或了两次dis[tmp]相当于没有异或
直接算dis[u]^dis[v]就可以了
所以我们就可以去掉求lca的部分
那么就只需要预处理出dis就可以了,一个dfs就行了

#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 100000 + 10;
vector<pair<int,int> > edges[maxn];
int n,m,dis[maxn];
inline void dfs(int now,int f,int Xor) {
    dis[now] = Xor;
    for (size_t i = 0;i < edges[now].size();i++)
        if (edges[now][i].first != f) dfs(edges[now][i].first,now,Xor^edges[now][i].second);
}
int main() {
    scanf("%d",&n);
    for (int i = 1,u,v,w;i < n;i++) {
        scanf("%d%d%d",&u,&v,&w);
        edges[u].push_back(make_pair(v,w));
        edges[v].push_back(make_pair(u,w));
    }
    dfs(1,1,1);
    scanf("%d",&m);
    for (int i = 1,u,v;i <= m;i++) {
        scanf("%d%d",&u,&v);
        printf("%d\n",dis[u]^dis[v]);
    }
    return 0;
}

  

luogu2420 让我们异或吧的更多相关文章

  1. Luogu2420 让我们异或吧 (熟练剖分)

    \(dis[u] \bigoplus dis[v] = dis[u] \bigoplus dis[v] \bigoplus dis[lca\{x,y\}] \bigoplus dis[lca\{x,y ...

  2. Android数据加密之异或加密算法

    前言: 这几天被公司临时拉到去做Android IM即时通信协议实现,大致看了下他们定的协议,由于之前没有参与,据说因服务器性能限制,只达成非明文传递,具体原因我不太清楚,不过这里用的加密方式是采用异 ...

  3. Oracle数据库异机升级

    环境: A机:RHEL5.5 + Oracle 10.2.0.4 B机:RHEL5.5 需求: A机10.2.0.4数据库,在B机升级到11.2.0.4,应用最新PSU补丁程序. 目录: 一. 确认是 ...

  4. [LeetCode] Maximum XOR of Two Numbers in an Array 数组中异或值最大的两个数字

    Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231. Find the maximum re ...

  5. [PHP][位转换积累]之异或运算的简单加密应用

    异或的符号是^.按位异或运算, 对等长二进制模式按位或二进制数的每一位执行逻辑按位异或操作. 操作的结果是如果某位不同则该位为1, 否则该位为0. xor运算的逆运算是它本身,也就是说两次异或同一个数 ...

  6. Poj The xor-longest Path 经典题 Trie求n个数中任意两个异或最大值

    Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5646   Accepted: 1226 Description In an ...

  7. RMAN异机恢复遭遇ORA-01547、ORA-01152、ORA-01110错误案例

    测试环境:     操作系统  :  Red Hat Enterprise Linux ES release 4 (Nahant Update 4)   VMWARE     数据库     :  O ...

  8. RAC异机恢复

    RAC异机恢复PDCL到PFCL: PNCL:RAC+ASM ,product env   db name:PNCL   instance:PDCL1 PDCL2 PFCL:RAC+ASM ,perf ...

  9. BZOJ 3261: 最大异或和

    Description 一个序列,支持两个操作. 1.在序列尾加入一个数. 2.询问 [l,r] 中与 x 异或值最大的数. \(n\leqslant 3*10^5\) Sol 可持久化 Trie 树 ...

随机推荐

  1. 设备常用框架framework

    framework名称 framework说明 framework文档 Accelerate.framework 包含加速数学和DSP函数 http://developer.apple.com/iph ...

  2. HDOJ-2009 求数列的和

    Problem Description 数列的定义如下:数列的第一项为n,以后各项为前一项的平方根,求数列的前m项的和.   Input 输入数据有多组,每组占一行,由两个整数n(n<10000 ...

  3. HTML5 开发APP(MUI的一些特性)

    先附mui文档地址:http://dev.dcloud.net.cn/mui/ui/  .mui的UI组件比较简单而且在文档中很好找就不过多说了. 1 在app开发中,使用HTML5+的api,必须m ...

  4. app中rem算法

    第一次用vue做APP被rem坑惨了 下面贴出 rem 的算法及使用方法 在自定义js中定义函数 export default { install: function(Vue, options) { ...

  5. 《MVC实现用户权限》

    用树形的结构显示权限的结构,树形结构的用的是jquery的控件 1. 赋给用户一个userid,在用户角色表将用户和角色关联起来,在角色权限表中将角色和权限对应起来,权限表中存储的是菜单栏的名称. 2 ...

  6. 9.Spark Streaming

    Spark Streaming 1 Why Apache Spark 2 关于Apache Spark 3 如何安装Apache Spark 4 Apache Spark的工作原理 5 spark弹性 ...

  7. 学生成绩管理系统——C语言实现

    一.功能实现: 0.浏览学生信息 1.输入学生信息 2.增加学生信息 3.修改学生信息 4.删除学生信息 5.按学号查询 6.按班级查询 7.按姓名查询 8.按课堂名称查询 9.按总分高低排序 10. ...

  8. Pandas: 如何将一列中的文本拆分为多行? | Python

    Pandas: 如何将一列中的文本拆分为多行? 在数据处理过程中,经常会遇到以下类型的数据: 在同一列中,本该分别填入多行中的数据,被填在一行里了,然而在分析的时候,需要拆分成为多行. 在上图中,列名 ...

  9. 大数据算法->推荐系统常用算法之基于内容的推荐系统算法

    港真,自己一直非常希望做算法工程师,所以自己现在开始对现在常用的大数据算法进行不断地学习,今天了解到的算法,就是我们生活中无处不在的推荐系统算法. 其实,向别人推荐商品是一个很常见的现象,比如我用了一 ...

  10. 3.commonjs模块

    1.首先建一个math.js exports.add = function(a, b){ return a + b; } exports.sub = function(a, b){ return a ...