建立字典树是异或的一种处理方法。

Description

In an edge-weighted tree, the xor-length of a path p is defined as the xor sum of the weights of edges on p:

$$_{xor}length(p)=\bigoplus _{e\in p}w(e)$$

$\bigoplus$ is the xor operator.

We say a path the xor-longest path if it has the largest xor-length. Given an edge-weighted tree with n nodes, can you find the xor-longest path?

Input

The input contains several test cases. The first line of each test case contains an integer $n(1<=n<=100000)$, The following $n-1$ lines each contains three integers $u(0 \le u < n),v(0 \le v < n),w(0 \le w < 2^31)$, which means there is an edge between node $u$ and $v$ of length $w$.

Output

For each test case output the xor-length of the xor-longest path.

Sample Input

4
0 1 3
1 2 4
1 3 6

Sample Output

7

Hint

The xor-longest path is 0->1->2, which has length 7 (=3 $latex \bigoplus$ 4)

题解:

    题目要求找一条路径使得这条路径上的每条边异或和最大。对于朴素算法我们可以预处理树上前缀异或和,通过求任意两点的LCA,并把两条路径再异或得到答案更新(异或是有结合律的)。这样的时间复杂度是$O(n^2\log n)$。

    如果看出异或就是异或的逆运算,也就是$x\bigoplus y\bigoplus y=x$,就可以知道,我们直接将两点的树上异或前缀和再次异或,就相当于消去了二者LCA以上的部分,得出的结果就是两者唯一路径上的异或和。LCA以上的部分实际上是异或了一遍又异或回来了。

    此时我们只要枚举两个点,让它们的前缀和相异或就可以了,时间复杂度为$O(n^2)$。但是$latex 100,000$的数据需要更加优化。

    我们可不可以先存下所有点的异或前缀和,然后枚举每个点,在$O(1)$或$O(\log n)$的时间复杂度内找出已经存下的点的前缀和中与当前点的前缀和异或和最大的来更新答案呢?

    尽管与一个数的异或不满足任何RMQ问题的解法,但是我们是不是可以贪心呐?对于一个二进制数,我们要使得一个数与它的异或值最大,就要按位从大到小尽可能不同。也就是贪心的思想,即$(10000000)_2>(01111111)_2$。

101001001 (1)
110100100 (2)
100110011 (3)

    因为(2)与(1)在第6位(最右边是第0位)就出现了不同,因此(1)跟(2)匹配是要比(3)优的。

    那我们要找到与一个数异或最大的,就可以把这个数给转成二进制,按位次从高到低建立字典树,深度越浅,贪心程度越大。因此贪心得出的结果总是唯一最优的。这里用了动态开点,不然找到了不存在的数,计算就会出现错误。

    这棵字典树也就是一棵二叉树,我们就要尽可能朝与当前位相反的地方走;如果没有相反的就只好顺着走了。并且因为每条链深度都是31的,所以不用担心访问到空节点。

Code:

#include<cstdio>
#include<cstring>
struct node
{
int down;
node *ls,*rs;
node()
{
ls=NULL;
rs=NULL;
}
void build(int x,int k)//开点的过程
{
if(k==-1)
return;
if((x>>k)&1)
{
if(!rs)
rs=new node();
rs->build(x,k-1);
}
else
{
if(!ls)
ls=new node();
ls->build(x,k-1);
}
}
int inv(int x,int k)//求尽可能多的相反能造成多少贡献
{
if(k<0)
return 0;
if((x>>k)&1)
{
if(ls)
return (1<<k)+ls->inv(x,k-1);
else
return rs->inv(x,k-1);
}
else
{
if(rs)
return (1<<k)+rs->inv(x,k-1);
else
return ls->inv(x,k-1);
}
}
}*root;
struct edge//建树
{
int n,v,nxt;
edge(int n,int nxt,int v)
{
this->n=n;
this->v=v;
this->nxt=nxt;
}
edge()
{
nxt=-1;
} }e[220000];
int head[100100],ecnt=-1;
void add(int from,int to,int v)
{
e[++ecnt]=edge(to,head[from],v);
head[from]=ecnt;
e[++ecnt]=edge(from,head[to],v);
head[to]=ecnt;
}
int sum[100100];
void dfs(int x,int from)
{
for(int i=head[x];~i;i=e[i].nxt)
if(e[i].n!=from)
{
sum[e[i].n]=(sum[x]^e[i].v);
dfs(e[i].n,x);
}
return;
}
int main()
{
root=new node();
memset(head,-1,sizeof(head));
int n,u,v,w;
scanf("%d",&n);
for(int i=1;i<n;++i)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
sum[1]=0;
dfs(1,1);
for(int i=1;i<=n;++i)
root->build(sum[i],30);
int ans=0;
for(int i=1;i<=n;++i)
{
int tmp=root->inv(sum[i],30);
ans=ans>tmp?ans:tmp;
}
printf("%d\n",ans);
return 0;
}

  

【字典树】【树】【二进制】bzoj1954/POJ3764The xor-longest Path 题解的更多相关文章

  1. poj3764 The XOR Longest Path【dfs】【Trie树】

    The xor-longest Path Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10038   Accepted:  ...

  2. 题解 bzoj1954【Pku3764 The xor – longest Path】

    做该题之前,至少要先会做这道题. 记 \(d[u]\) 表示 \(1\) 到 \(u\) 简单路径的异或和,该数组可以通过一次遍历求得. \(~\) 考虑 \(u\) 到 \(v\) 简单路径的异或和 ...

  3. 【转】B树、B-树、B+树、B*树、红黑树、 二叉排序树、trie树Double Array 字典查找树简介

    B  树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: ...

  4. CSU - 1551 Longest Increasing Subsequence Again —— 线段树/树状数组 + 前缀和&后缀和

    题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1551 题意: 给出一段序列, 删除其中一段连续的子序列(或者不删), 使得剩下的序列 ...

  5. 【BZOJ 3626】 [LNOI2014]LCA【在线+主席树+树剖】

    题目链接: TP 题解:   可能是我比较纱布,看不懂题解,只好自己想了…… 先附一个离线版本题解[Ivan] 我们考虑对于询问区间是可以差分的,然而这并没有什么卵用,然后考虑怎么统计答案. 首先LC ...

  6. 主席树+树链剖分——南昌邀请赛Distance on the tree

    学了差不多一星期的主席树+树链剖分,再来看这题发现其实是个板子题 一开始想复杂了,以为要用类似求树上第k大的树上差分思想来解决这道题,但其实树链上<=k的元素个数其实直接可以用树链剖分来求 具体 ...

  7. HDU 3333 Turing Tree 离线 线段树/树状数组 区间求和单点修改

    题意: 给一个数列,一些询问,问你$[l,r]$之间不同的数字之和 题解: 11年多校的题,现在属于"人尽皆知傻逼题" 核心思想在于: 对于一个询问$[x,R]$ 无论$x$是什么 ...

  8. acm 2015北京网络赛 F Couple Trees 主席树+树链剖分

    提交 题意:给了两棵树,他们的跟都是1,然后询问,u,v 表 示在第一棵树上在u点往根节点走 , 第二棵树在v点往根节点走,然后求他们能到达的最早的那个共同的点 解: 我们将第一棵树进行书链剖,然后第 ...

  9. BZOJ1146 [CTSC2008]网络管理Network 树链剖分 主席树 树状数组

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1146 题意概括 在一棵树上,每一个点一个权值. 有两种操作: 1.单点修改 2.询问两点之间的树链 ...

  10. 洛谷P3960 列队 NOIp2017 线段树/树状数组/splay

    正解:动态开点线段树 解题报告: 传送门! 因为最近学主席树的时候顺便get到了动态开点线段树?刚好想起来很久很久以前就想做结果一直麻油做的这题,,,所以就做下好了QAQ 然后说下,这题有很多种方法, ...

随机推荐

  1. Qt入门-第一个Qt程序

    在安装完之后,迫不及待创建第一个Qt  demo

  2. 496. Next Greater Element I 另一个数组中对应的更大元素

    [抄题]: You are given two arrays (without duplicates) nums1 and nums2 where nums1’s elements are subse ...

  3. ubuntu 16.04 ARM glog移植

    1. 下载源文件https://github.com/google/glog 2. 源文件有CMakeLists.txt, 直接使用toolchain.cmake 直接编译就可以了,详情参考我的随笔  ...

  4. Luogu 2704 [NOI2001]炮兵阵地

    唔,想到了状压之后就不会了……实在是菜 考虑压两行,设$f_{i, j, k}$表示当前到第$i$行,上一行是$j$状态,前一行是$k$状态的最多能放的炮兵的数量. 发现第一维还可以滚掉,好像可以转移 ...

  5. jquery表单数据反序列化为字典

    .前台代码 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1 ...

  6. oracle数据库登录

    在做以下操作时,要确保你的数据库环境已经正确安装完成.数据库在实际应用中是比较多的,我们测试人员经常会在前台造一些测试数据,在后台数据库进行验证,当然,不局限于此,数据库也可以作为一个专项测试来谈.反 ...

  7. javaweb dom4j解析xml文档

    1.什么是dom4j dom4j是一个Java的XML API,是jdom的升级品,用来读写XML文件的.dom4j是一个十分优秀的JavaXML API,具有性能优异.功能强大和极其易使用的特点,它 ...

  8. Django实战之古风博客

    感谢 感谢杨青 大大的古风模板,设计的很棒,给个赞. 如有侵权,请联系我 运行环境 python3.6 Django==1.11.4 django-ckeditor==5.4.0 django-js- ...

  9. MongoDB整理笔记の安装及配置

    1.官网下载 地址:http://www.mongodb.org/downloads mongodb-linux-x86_64-2.4.9.tgz (目前为止,64位最新版本) 2.解压 切换到下载目 ...

  10. windowsPhone一些不常见控件

    1.InkPresenter:可以产生手写效果的控件. http://www.cnblogs.com/randylee/archive/2010/08/10/1791222.html 2.Thumb: ...