Tree

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)
Total Submission(s): 1643    Accepted Submission(s): 461

Problem Description
  Zero and One are good friends who always have fun with each other. This time, they decide to do something on a tree which is a kind of graph that there is only one path from node to node. First, Zero will give One an tree and every node in this tree has a value. Then, Zero will ask One a series of queries. Each query contains three parameters: x, y, z which mean that he want to know the maximum value produced by z xor each value on the path from node x to node y (include node x, node y). Unfortunately, One has no idea in this question. So he need you to solve it.
 
Input
  There are several test cases and the cases end with EOF. For each case:

The first line contains two integers n(1<=n<=10^5) and m(1<=m<=10^5), which are the amount of tree’s nodes and queries, respectively.

The second line contains n integers a[1..n] and a[i](0<=a[i]<2^{16}) is the value on the ith node.

The next n–1 lines contains two integers u v, which means there is an connection between u and v.

The next m lines contains three integers x y z, which are the parameters of Zero’s query.

 
Output
  For each query, output the answer.

 
Sample Input
3 2
1 2 2
1 2
2 3
 
1 3 1
2 3 2
 
Sample Output
3
0
 

题目链接:HDU 4757

一道跟COT很像的题,但是用的是可持久化的Trie,做法跟COT基本相同,但是过程中由于N少设了10倍,无限TLE……各种纠结问题出在Tarjan?并查集?插入查询函数?因此过程中还找了题解但发现并没有什么区别,但有另外一种非递归形式的插入查询写法,值得借鉴。另外处理节点LCA的问题上公式还是那条$cnt_{U,V}=cnt_{U}+cnt_{V}-cnt_{LCA}-cnt_{father[LCA]}$

单纯地减掉两倍可能会出错,不知道网上的例程是什么情况。通过最近几道题了解了可持久化Trie的空间复杂度似乎跟Trie是一样的,都是Total*maxlen(如果撇开相对来说只有一丢丢的root数组不说的话)

递归更新查询的代码:

  1. #include <stdio.h>
  2. #include <iostream>
  3. #include <algorithm>
  4. #include <cstdlib>
  5. #include <sstream>
  6. #include <cstring>
  7. #include <bitset>
  8. #include <string>
  9. #include <deque>
  10. #include <stack>
  11. #include <cmath>
  12. #include <queue>
  13. #include <set>
  14. #include <map>
  15. using namespace std;
  16. #define INF 0x3f3f3f3f
  17. #define CLR(arr,val) memset(arr,val,sizeof(arr))
  18. #define LC(x) (x<<1)
  19. #define RC(x) ((x<<1)+1)
  20. #define MID(x,y) ((x+y)>>1)
  21. typedef pair<int,int> pii;
  22. typedef long long LL;
  23. const double PI=acos(-1.0);
  24. const int N=1e5+7;
  25. struct Trie
  26. {
  27. int nxt[2];
  28. int cnt;
  29. };
  30. struct edge
  31. {
  32. int to,nxt;
  33. };
  34. struct Query
  35. {
  36. int to,nxt,id,lca;
  37. };
  38. struct ask
  39. {
  40. int u,v,lca,val;
  41. };
  42. ask q[N];
  43. Trie L[N*18];int cnt;
  44. Query Q[N<<1];int qtot,qhead[N];
  45. edge E[N<<1];int tot,head[N];
  46. int ances[N],pre[N],Father[N];
  47. bitset<N>vis;
  48. int arr[N],root[N];
  49.  
  50. void init()
  51. {
  52. CLR(L,0);cnt=0;
  53. CLR(head,-1);tot=0;
  54. CLR(qhead,-1);qtot=0;
  55. CLR(ances,0);
  56. for (int i=0; i<N; ++i)
  57. pre[i]=i;
  58. CLR(Father,0);
  59. vis.reset();
  60. CLR(root,0);
  61. }
  62. inline void add(const int &s,const int &t)
  63. {
  64. E[tot].to=t;
  65. E[tot].nxt=head[s];
  66. head[s]=tot++;
  67. }
  68. inline void addQ(const int &s,const int &t,const int &id)
  69. {
  70. Q[qtot].to=t;
  71. Q[qtot].id=id;
  72. Q[qtot].lca=1;
  73. Q[qtot].nxt=qhead[s];
  74. qhead[s]=qtot++;
  75. }
  76.  
  77. void update(int &cur,const int &ori,const int &step,const int &n)
  78. {
  79. cur=++cnt;
  80. L[cur]=L[ori];
  81. ++L[cur].cnt;
  82. if(step<0)
  83. return;
  84. int t=(n>>step)&1;
  85. update(L[cur].nxt[t],L[ori].nxt[t],step-1,n);
  86. }
  87. int Find(const int &n)
  88. {
  89. return n==pre[n]?n:pre[n]=Find(pre[n]);
  90. }
  91. void Tarjan(const int &u,const int &Fa)
  92. {
  93. vis[u]=1;
  94. ances[u]=u;
  95. Father[u]=Fa;
  96. update(root[u],root[Fa],16,arr[u]);
  97. for (int i=head[u]; ~i; i=E[i].nxt)
  98. {
  99. int v=E[i].to;
  100. if(!vis[v])
  101. {
  102. Tarjan(v,u);
  103. pre[v]=u;
  104. ances[Find(u)]=u;
  105. }
  106. }
  107. for (int i=qhead[u]; ~i; i=Q[i].nxt)
  108. {
  109. int v=Q[i].to;
  110. if(vis[v])
  111. q[Q[i].id].lca=ances[Find(v)];
  112. }
  113. }
  114. int query(const int &U,const int &V,const int &LCA,const int &F_LCA,const int &step,const int &n)
  115. {
  116. if(step<0)
  117. return 0;
  118. int t=(n>>step)&1;
  119. int c=L[L[U].nxt[t^1]].cnt+L[L[V].nxt[t^1]].cnt-L[L[LCA].nxt[t^1]].cnt-L[L[F_LCA].nxt[t^1]].cnt;
  120. if(c>0)
  121. return (1<<step)+query(L[U].nxt[t^1],L[V].nxt[t^1],L[LCA].nxt[t^1],L[F_LCA].nxt[t^1],step-1,n);
  122. else
  123. return query(L[U].nxt[t],L[V].nxt[t],L[LCA].nxt[t],L[F_LCA].nxt[t],step-1,n);
  124. }
  125. int main(void)
  126. {
  127. int n,m,a,b,i;
  128. while (~scanf("%d%d",&n,&m))
  129. {
  130. init();
  131. for (i=1; i<=n; ++i)
  132. scanf("%d",&arr[i]);
  133. for (i=0; i<n-1; ++i)
  134. {
  135. scanf("%d%d",&a,&b);
  136. add(a, b);
  137. add(b, a);
  138. }
  139. for (i=0; i<m; ++i)
  140. {
  141. scanf("%d%d%d",&q[i].u,&q[i].v,&q[i].val);
  142. addQ(q[i].u, q[i].v, i);
  143. addQ(q[i].v, q[i].u, i);
  144. }
  145. Tarjan(1,0);
  146. for (i=0; i<m; ++i)
  147. printf("%d\n",query(root[q[i].u],root[q[i].v],root[q[i].lca],root[Father[q[i].lca]],16,q[i].val));
  148. }
  149. return 0;
  150. }

网上例程的非递归写法:

  1. int update(int ori,int n)
  2. {
  3. bitset<17> s=n;
  4. int cur=++cnt;
  5. int ret=cur;
  6. L[cur]=L[ori];
  7. for (int i=16; i>=0; --i)
  8. {
  9. int v=s[i];
  10. L[++cnt]=L[L[cur].nxt[v]];
  11. ++L[cnt].cnt;
  12. L[cur].nxt[v]=cnt;
  13. cur=cnt;
  14. }
  15. return ret;
  16. }
  17. void Tarjan(const int &u,const int &Fa)
  18. {
  19. /*vis[u]=1;
  20. ances[u]=u;
  21. Father[u]=Fa;*/
  22. root[u]=update(root[Fa],arr[u]);
  23. /*for (int i=head[u]; ~i; i=E[i].nxt)
  24. {
  25. int v=E[i].to;
  26. if(!vis[v])
  27. {
  28. Tarjan(v,u);
  29. pre[v]=u;
  30. ances[Find(u)]=u;
  31. }
  32. }
  33. for (int i=qhead[u]; ~i; i=Q[i].nxt)
  34. {
  35. int v=Q[i].to;
  36. if(vis[v])
  37. q[Q[i].id].lca=ances[Find(v)];
  38. }*/
  39. }
  40. int query(int u,int v,int lca,int flca,int n)
  41. {
  42. int r=0;
  43. bitset<17> s=n;
  44. for (int i=16; i>=0; --i)
  45. {
  46. int indx=s[i];
  47. int c=L[L[u].nxt[indx^1]].cnt+L[L[v].nxt[indx^1]].cnt-L[L[lca].nxt[indx^1]].cnt-L[L[flca].nxt[indx^1]].cnt;
  48. if(c>0)
  49. {
  50. r+=1<<i;
  51. u=L[u].nxt[indx^1];
  52. v=L[v].nxt[indx^1];
  53. lca=L[lca].nxt[indx^1];
  54. flca=L[flca].nxt[indx^1];
  55. }
  56. else
  57. {
  58. u=L[u].nxt[indx];
  59. v=L[v].nxt[indx];
  60. lca=L[lca].nxt[indx];
  61. flca=L[flca].nxt[indx];
  62. }
  63. }
  64. return r;
  65. }

HDU 4757 Tree(可持久化Trie+Tarjan离线LCA)的更多相关文章

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

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

  2. HDU 4757 Tree 可持久化字典树 trie

    http://acm.hdu.edu.cn/showproblem.php?pid=4757 给出一棵树,每个节点有权值,每次查询节点 (u,v) 以及 val,问 u 到 v 路径上的某个节点与 v ...

  3. HDU 4757 Tree 可持久化字典树

    Tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4757 Des ...

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

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

  5. HDU 4757 Tree

    传送门 Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others) Prob ...

  6. SPOJ 10628 Count on a tree(Tarjan离线LCA+主席树求树上第K小)

    COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to  ...

  7. HDU 4757 Tree(可持久化字典树)(2013 ACM/ICPC Asia Regional Nanjing Online)

    Problem Description   Zero and One are good friends who always have fun with each other. This time, ...

  8. HDU4757 Tree(可持久化Trie)

    写过可持久化线段树,但是从来没写过可持久化的Trie,今天补一补. 题目就是典型的给你一个数x,和一个数集,问x和里面的某个数xor起来的最大值是多少. 最原始的是数集是固定的,只需要对数集按照高到低 ...

  9. HDU 4757 Tree(可持续化字典树,lca)

    题意:询问树上结点x到结点y路上上的权值异或z的最大值. 任意结点权值 ≤ 2^16,可以想到用字典树. 但是因为是询问某条路径上的字典树,将字典树可持续化,字典树上的结点保存在这条路径上的二进制数. ...

随机推荐

  1. poj 1695

    用动态规划,dp[a][b][c]表示从位置最大的车在a(注意不是第一辆车),第二的车在b,第三的车在c开始最少需要的时间. 方程:dp[a][b][c]=max{dp[a+1][b][c],     ...

  2. iOS 8.0后使用UIAlertController

    iOS 8的新特性之一就是让接口更有适应性.更灵活,因此许多视图控制器的实现方式发生了巨大的变化.全新的UIPresentationController在实现视图控制器间的过渡动画效果和自适应设备尺寸 ...

  3. Python: zip函数

    zip函数接受任意多个(包括0个和1个)序列作为参数,返回一个tuple列表. 参考链接解释

  4. realloc的使用误区

    C语言 realloc() 函数位于 stdlib.h 头文件中,原型为: void *realloc(void *ptr, size_t size); realloc() 会将 ptr 所指向的内存 ...

  5. NEFU 561 方块计算

    题目链接 简单搜索题 #include <cstdio> #include <iostream> #include <cstring> using namespac ...

  6. 使用vs2008搭建php扩展环境

    所需要的工具或者文件: 1.php源码,去官网下载即可.http://windows.php.net/download 2.php-sdk:php 开发工具包 3.deps类库 4.Cygwin:wi ...

  7. PHP获取当前位置

    如果想动态的获取当前栏目所处的位置,就要关联到数据库,下面是例子: 栏目表(category): 涉及到二级目录. (1)首先在你的首页导航栏,还有首页所出现的链接后面,为栏目加上catid,就像这样 ...

  8. 根据字体计算CGRect

    UILabel *label = [[UILabel alloc]init]; label.numberOfLines = ;//多行显示 label.backgroundColor = [UICol ...

  9. C语言中的强符号与弱符号

    转自:http://blog.csdn.net/astrotycoon/article/details/8008629 一.概述 在C语言中,函数和初始化的全局变量(包括显示初始化为0)是强符号,未初 ...

  10. AutoMapper搬运工之自定义类型转换

    前言 最近还挺忙,还有点累,一直都没更新了,实在是懒呀.正题之前先说点别的,最近公司要扩张了,需要大量开发,领导说推荐有钱可以拿,如此好机会,我就趁机做个广告.ShippingRen.com招募.NE ...