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

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. 项目代码:js

    1 //获取发文时间 function selectWriteTime(){ $("#writing_time_index").on("click"," ...

  2. 编写高质量代码改善C#程序的157个建议——建议52:及时释放资源

    建议52:及时释放资源 垃圾回收机制自动为我们隐式地回收了资源(垃圾回收器会自动调用终结器),那我们为什么要主动释放资源呢? private void buttonOpen_Click(object ...

  3. C# int?

    int?:表示可空类型,就是一种特殊的值类型,它的值可以为null用于给变量设初值得时候,给变量(int类型)赋值为null,而不是0int??:用于判断并赋值,先判断当前变量是否为null,如果是就 ...

  4. 检查Windows上安装的.net版本

    cmd reg query "HKLM\Software\Microsoft\NET Framework Setup\NDP" /s /v version | findstr /i ...

  5. 小程序上传多图片多附件多视频 c#后端

    前言: 最近在研究微信小程序,本人自己是C#写后端的;感觉小程序挺好玩的,就自己研究了一下:刚好今天又给我需求,通过小程序上传多图 然后C#后端保存到服务器: 用NET明白 前端上传需要用到流,然后就 ...

  6. php 可变数量的参数列表

    可变数量的参数列表 PHP 在用户自定义函数中支持可变数量的参数列表.在 PHP 5.6 及以上的版本中,由 ... 语法实现:在 PHP 5.5 及更早版本中,使用函数func_num_args() ...

  7. L - Ch’s gift HDU - 6162

    Ch’s gift Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  8. Eclipse下的Hadoop应用开发准备

    window下开发的准备: A.在windows的某个目录下解压一个hadoop的安装包 B.将安装包下的lib和bin目录用对应windows版本平台编译的本地库替换 C.在window系统中配置H ...

  9. PHP的Composer 与 Packagist,简单入门

    [转]http://www.php.cn/manual/view/34000.html Composer 是一个 杰出 的依赖管理器.在 composer.json 文件中列出你项目所需的依赖包,加上 ...

  10. 查看linux操作系统的版本等信息

    1.查看操作系统是32位还是64位的命令: (1)getconf LONG_BIT (2)uname -a (3)uname -m (4)arch (5)file /sbin/init 2.查看操作系 ...