写过可持久化线段树,但是从来没写过可持久化的Trie,今天补一补。

题目就是典型的给你一个数x,和一个数集,问x和里面的某个数xor起来的最大值是多少。

最原始的是数集是固定的,只需要对数集按照高到低位去建Trie,然后贪心匹配就可以了。

这里则是对树上路径的操作,其实也是一样的,对每个节点x维护root到x的Trie,然后纪录下往左走往右走的叶子节点个数,设z=lca(x,y),那么到了个某个节点能否往某个儿子走的限制条件是 sz[ch[x][c]]+sz[ch[y][c]]-2*sz[ch[z][c]]>0,这样说明下面是存在c的儿子的,接着往下走即可。当然这样算其实是会漏掉lca的,所以最后还要和lca取最大值。

区间的询问作为这题的特例同理也是可以处理的。

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <string>
  5. #include <algorithm>
  6. #include <cmath>
  7. #include <queue>
  8. #include <cassert>
  9. #include <vector>
  10. #include <set>
  11. using namespace std;
  12.  
  13. #define maxn 120000
  14. #define maxnode 2200000
  15. #define maxlogv 16
  16. vector<int> G[maxn];
  17. int n,m;
  18. int a[maxn];
  19.  
  20. int f[maxlogv+2][maxn];
  21. int dep[maxn];
  22. int ch[maxnode][2];
  23. int sz[maxnode];
  24. int tot;
  25. int root[maxn];
  26.  
  27. int newnode(){
  28. memset(ch[tot],0,sizeof(ch[tot]));
  29. sz[tot]=0;
  30. return tot++;
  31. }
  32.  
  33. // insert val for x with father as y
  34. void insert(int x,int y,int val)
  35. {
  36. x=root[x];y=root[y];
  37. for(int i=15;i>=0;--i){
  38. int c=(val>>i)&1;
  39. if(!ch[x][c]){
  40. int id=newnode();
  41. ch[x][c]=id;
  42. ch[x][!c]=ch[y][!c];
  43. sz[ch[x][c]]=sz[ch[y][c]];
  44. }
  45. x=ch[x][c],y=ch[y][c];
  46. ++sz[x];
  47. }
  48. }
  49.  
  50. void dfs(int u,int fa)
  51. {
  52. f[0][u]=fa;dep[u]=dep[fa]+1;
  53. root[u]=newnode();
  54. insert(u,fa,a[u]);
  55. for(int i=0;i<G[u].size();++i){
  56. int v=G[u][i];
  57. if(v==fa) continue;
  58. dfs(v,u);
  59. }
  60. }
  61.  
  62. int lca(int u,int v)
  63. {
  64. if(dep[u]>dep[v]) swap(u,v);
  65. for(int k=0;k<maxlogv;++k){
  66. if( (dep[v]-dep[u])>>k&1){
  67. v=f[k][v];
  68. }
  69. }
  70. if(u==v) return u;
  71. for(int k=maxlogv-1;k>=0;--k){
  72. if(f[k][u]!=f[k][v]){
  73. u=f[k][u];
  74. v=f[k][v];
  75. }
  76. }
  77. return f[0][u];
  78. }
  79.  
  80. int query(int x,int y,int val)
  81. {
  82. int z=lca(x,y);int res=a[z]^val;
  83. x=root[x],y=root[y],z=root[z];
  84. int ret=0;
  85. for(int i=15;i>=0;--i){
  86. int c=(val>>i)&1;
  87. if(sz[ch[x][!c]]+sz[ch[y][!c]]-2*sz[ch[z][!c]]>0){
  88. ret+=1<<i;
  89. c=!c;
  90. }
  91. x=ch[x][c];
  92. y=ch[y][c];
  93. z=ch[z][c];
  94. }
  95. return max(ret,res);
  96. }
  97.  
  98. int main()
  99. {
  100. while(cin>>n>>m){
  101. for(int i=1;i<=n;++i){
  102. scanf("%d",a+i);
  103. G[i].clear();
  104. }
  105. int ui,vi;
  106. for(int i=0;i<n-1;++i){
  107. scanf("%d%d",&ui,&vi);
  108. G[ui].push_back(vi);
  109. G[vi].push_back(ui);
  110. }
  111. memset(root,0,sizeof(root));
  112. tot=1;
  113. memset(f,0,sizeof(f));
  114. memset(sz,0,sizeof(sz));
  115. dep[0]=0;
  116. dfs(1,0);
  117. for(int k=0;k+1<maxlogv;++k){
  118. for(int v=1;v<=n;++v){
  119. if(f[k][v]==0) f[k+1][v]=0;
  120. else f[k+1][v]=f[k][f[k][v]];
  121. }
  122. }
  123. int xi,yi,zi;
  124. for(int i=0;i<m;++i){
  125. scanf("%d%d%d",&xi,&yi,&zi);
  126. printf("%d\n",query(xi,yi,zi));
  127. }
  128. }
  129. return 0;
  130. }

HDU4757 Tree(可持久化Trie)的更多相关文章

  1. HDU.4757.Tree(可持久化Trie)

    题目链接 \(Description\) 给定一棵树,点有点权.\(Q\)次询问\(x,y,z\),求\(x\)到\(y\)的简单路径中,与\(z\)异或能得到的最大的数是多少. \(Solution ...

  2. hdu4757(可持久化 Trie )

    hdu4757 题意 给出一棵树,每个节点有权值,每次查询节点 \((u, v)\) 以及 \(x\) ,问 \(u\) 到 \(v\) 路径上的某个节点与 \(x\) 异或最大的值是多少. 分析 T ...

  3. Hdu-4757 Tree(可持久化字典树+lca)

    题目链接:点这 我的github地址:点这     Problem Description   Zero and One are good friends who always have fun wi ...

  4. HDU 4757 Tree(可持久化Trie+Tarjan离线LCA)

    Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Total Su ...

  5. HDU 4757 Tree(可持久化trie)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4757 题意:给出一棵树,节点有权值.每次询问x到y的路径上与z抑或的最大值. 思路:可持久化trie. ...

  6. HDU 6191 Query on A Tree ( 2017广西邀请赛 && 可持久化Trie )

    题目链接 题意 : 给你一棵树.树上的每个点都有点权.之后有若干次问询.每次问询给出一个节点编号以及一个整数 X .问你以给出节点为根的子树中哪个节点和 X 异或最大.输出这个值 分析 : 看到这种树 ...

  7. HDU4757--Tree 可持久化trie + LCA

    题意:n个点的树,Q次询问,询问u-v路径上的点的权值与z抑或的最大值. 先考虑,在一个区间上的问题,可以先建一个可持久化的Trie,然后每次询问,就和线段树的操作差不多,从最高位开始考虑选1还是选0 ...

  8. hdu 6191--Query on A Tree(持久化字典树)

    题目链接 Problem Description Monkey A lives on a tree, he always plays on this tree. One day, monkey A l ...

  9. 可持久化 trie 的简单入门

    可持久化 $trie$  ....又是一个表里不一的东西..... 可持久化 $trie$  的介绍: 和主席树类似的,其实可持久化就是体现在前缀信息的维护上(搞不懂这怎么就叫做可持久化了...) $ ...

随机推荐

  1. POJ 2299 Ultra-QuickSort 简单题解

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 68874   Accepted: 25813 ...

  2. Broken robot CodeForces - 24D (概率DP)

    You received as a gift a very clever robot walking on a rectangular board. Unfortunately, you unders ...

  3. 使用观察者模式更新Fragment的内容

    最近有个需求,就是在Fragment没有切换的时候(show,hide)更新Fragment显示的内容,想了一会,终于想到可以用观察者模式来解决这个问题的. 定义一个[被观察者(接口)]: publi ...

  4. android抓取logcat日志的方法

    这几天帮忙测试一个APP,报告结果需要提交日志文件,于是百度了下安卓的获取日志方法,其实很简单,7个步骤搞定,下面把我的总结分享给大家. 1.下载adb工具包 https://pan.baidu.co ...

  5. Java类和对象 详解(一)---写的很好通俗易懂---https://blog.csdn.net/wei_zhi/article/details/52745268

    https://blog.csdn.net/wei_zhi/article/details/52745268

  6. Python基础-week06 面向对象编程基础

    一.面向对象编程 1.面向过程 与 面向对象编程 面向过程的程序设计: 核心是 过程二字,过程指的是解决问题的步骤,即先干什么再干什么......面向过程的设计就好比精心设计好一条流水线,是一种机械式 ...

  7. PHP 删除 url 中的 query string

    function removeQueryStringFromUrl($url) { if (substr($url,0,4) =="http") { $urlPartsArray ...

  8. js 遍历对象属性(for in、Object.keys、Object.getOwnProperty) 以及高效地输出 js 数组

    js中几种遍历对象的方法,包括for in.Object.keys.Object.getOwnProperty,它们在使用场景方面各有不同. for in 主要用于遍历对象的可枚举属性,包括自有属性. ...

  9. [转]核函数K(kernel function)

    1 核函数K(kernel function)定义 核函数K(kernel function)就是指K(x, y) = <f(x), f(y)>,其中x和y是n维的输入值,f(·) 是从n ...

  10. linux系统mysql密码修改脚本

    编写了一个适用于阿里云linux系统 mysql密码修改脚本,使用阿里云提供的一键安装包配置后,如果account.log文件删除,并且忘记mysql密码时,可以通过脚本来重置mysql密码. 附:一 ...