SPOJ 10628. Count on a tree (树上第k大,LCA+主席树)

10628. Count on a tree

Problem code: COT

You are given a tree with N nodes.The tree nodes are numbered from 1 to N.Each node has an integer weight.

We will ask you to perform the following operation:

  • u v k : ask for the kth minimum weight on the path from node u to node v

Input

In the first line there are two integers N and M.(N,M<=100000)

In the second line there are N integers.The ith integer denotes the weight of the ith node.

In the next N-1 lines,each line contains two integers u v,which describes an edge (u,v).

In the next M lines,each line contains three integers u v k,which means an operation asking for the kth minimum weight on the path from node u to node v.

Output

For each operation,print its result.

Example

  1. Input:
8 5
  1. 8 5
  2. 105 2 9 3 8 5 7 7
  3. 1 2
  4. 1 3
  5. 1 4
  6. 3 5
  7. 3 6
  8. 3 7
  9. 4 8
    2 5 1
    2 5 2
    2 5 3
    2 5 4
    7 8 2 
  1. Output:
  2. 2
    8
    9
    105
    7 

在树上建立主席树。

然后求LCA

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <iostream>
  4. #include <algorithm>
  5. #include <vector>
  6. #include <queue>
  7. #include <set>
  8. #include <map>
  9. #include <string>
  10. #include <math.h>
  11. #include <stdlib.h>
  12. #include <time.h>
  13. using namespace std;
  14.  
  15. //主席树部分 *****************8
  16. const int MAXN = ;
  17. const int M = MAXN * ;
  18. int n,q,m,TOT;
  19. int a[MAXN], t[MAXN];
  20. int T[M], lson[M], rson[M], c[M];
  21.  
  22. void Init_hash()
  23. {
  24. for(int i = ; i <= n;i++)
  25. t[i] = a[i];
  26. sort(t+,t++n);
  27. m = unique(t+,t+n+)-t-;
  28. }
  29. int build(int l,int r)
  30. {
  31. int root = TOT++;
  32. c[root] = ;
  33. if(l != r)
  34. {
  35. int mid = (l+r)>>;
  36. lson[root] = build(l,mid);
  37. rson[root] = build(mid+,r);
  38. }
  39. return root;
  40. }
  41. int hash(int x)
  42. {
  43. return lower_bound(t+,t++m,x) - t;
  44. }
  45. int update(int root,int pos,int val)
  46. {
  47. int newroot = TOT++, tmp = newroot;
  48. c[newroot] = c[root] + val;
  49. int l = , r = m;
  50. while( l < r)
  51. {
  52. int mid = (l+r)>>;
  53. if(pos <= mid)
  54. {
  55. lson[newroot] = TOT++; rson[newroot] = rson[root];
  56. newroot = lson[newroot]; root = lson[root];
  57. r = mid;
  58. }
  59. else
  60. {
  61. rson[newroot] = TOT++; lson[newroot] = lson[root];
  62. newroot = rson[newroot]; root = rson[root];
  63. l = mid+;
  64. }
  65. c[newroot] = c[root] + val;
  66. }
  67. return tmp;
  68. }
  69. int query(int left_root,int right_root,int LCA,int k)
  70. {
  71. int lca_root = T[LCA];
  72. int pos = hash(a[LCA]);
  73. int l = , r = m;
  74. while(l < r)
  75. {
  76. int mid = (l+r)>>;
  77. int tmp = c[lson[left_root]] + c[lson[right_root]] - *c[lson[lca_root]] + (pos >= l && pos <= mid);
  78. if(tmp >= k)
  79. {
  80. left_root = lson[left_root];
  81. right_root = lson[right_root];
  82. lca_root = lson[lca_root];
  83. r = mid;
  84. }
  85. else
  86. {
  87. k -= tmp;
  88. left_root = rson[left_root];
  89. right_root = rson[right_root];
  90. lca_root = rson[lca_root];
  91. l = mid + ;
  92. }
  93. }
  94. return l;
  95. }
  96.  
  97. //LCA部分
  98. int rmq[*MAXN];//rmq数组,就是欧拉序列对应的深度序列
  99. struct ST
  100. {
  101. int mm[*MAXN];
  102. int dp[*MAXN][];//最小值对应的下标
  103. void init(int n)
  104. {
  105. mm[] = -;
  106. for(int i = ;i <= n;i++)
  107. {
  108. mm[i] = ((i&(i-)) == )?mm[i-]+:mm[i-];
  109. dp[i][] = i;
  110. }
  111. for(int j = ; j <= mm[n];j++)
  112. for(int i = ; i + (<<j) - <= n; i++)
  113. dp[i][j] = rmq[dp[i][j-]] < rmq[dp[i+(<<(j-))][j-]]?dp[i][j-]:dp[i+(<<(j-))][j-];
  114. }
  115. int query(int a,int b)//查询[a,b]之间最小值的下标
  116. {
  117. if(a > b)swap(a,b);
  118. int k = mm[b-a+];
  119. return rmq[dp[a][k]] <= rmq[dp[b-(<<k)+][k]]?dp[a][k]:dp[b-(<<k)+][k];
  120. }
  121. };
  122. //边的结构体定义
  123. struct Edge
  124. {
  125. int to,next;
  126. };
  127. Edge edge[MAXN*];
  128. int tot,head[MAXN];
  129.  
  130. int F[MAXN*];//欧拉序列,就是dfs遍历的顺序,长度为2*n-1,下标从1开始
  131. int P[MAXN];//P[i]表示点i在F中第一次出现的位置
  132. int cnt;
  133.  
  134. ST st;
  135. void init()
  136. {
  137. tot = ;
  138. memset(head,-,sizeof(head));
  139. }
  140. void addedge(int u,int v)//加边,无向边需要加两次
  141. {
  142. edge[tot].to = v;
  143. edge[tot].next = head[u];
  144. head[u] = tot++;
  145. }
  146. void dfs(int u,int pre,int dep)
  147. {
  148. F[++cnt] = u;
  149. rmq[cnt] = dep;
  150. P[u] = cnt;
  151. for(int i = head[u];i != -;i = edge[i].next)
  152. {
  153. int v = edge[i].to;
  154. if(v == pre)continue;
  155. dfs(v,u,dep+);
  156. F[++cnt] = u;
  157. rmq[cnt] = dep;
  158. }
  159. }
  160. void LCA_init(int root,int node_num)//查询LCA前的初始化
  161. {
  162. cnt = ;
  163. dfs(root,root,);
  164. st.init(*node_num-);
  165. }
  166. int query_lca(int u,int v)//查询u,v的lca编号
  167. {
  168. return F[st.query(P[u],P[v])];
  169. }
  170.  
  171. void dfs_build(int u,int pre)
  172. {
  173. int pos = hash(a[u]);
  174. T[u] = update(T[pre],pos,);
  175. for(int i = head[u]; i != -;i = edge[i].next)
  176. {
  177. int v = edge[i].to;
  178. if(v == pre)continue;
  179. dfs_build(v,u);
  180. }
  181. }
  182. int main()
  183. {
  184. //freopen("in.txt","r",stdin);
  185. //freopen("out.txt","w",stdout);
  186. while(scanf("%d%d",&n,&q) == )
  187. {
  188. for(int i = ;i <= n;i++)
  189. scanf("%d",&a[i]);
  190. Init_hash();
  191. init();
  192. TOT = ;
  193. int u,v;
  194. for(int i = ;i < n;i++)
  195. {
  196. scanf("%d%d",&u,&v);
  197. addedge(u,v);
  198. addedge(v,u);
  199. }
  200. LCA_init(,n);
  201. T[n+] = build(,m);
  202. dfs_build(,n+);
  203. int k;
  204. while(q--)
  205. {
  206. scanf("%d%d%d",&u,&v,&k);
  207. printf("%d\n",t[query(T[u],T[v],query_lca(u,v),k)]);
  208. }
  209. return ;
  210. }
  211. return ;
  212. }

LCA+主席树 (求树上路径点权第k大)的更多相关文章

  1. 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  ...

  2. SPOJ 10628 Count on a tree(Tarjan离线 | RMQ-ST在线求LCA+主席树求树上第K小)

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

  3. SPOJ COT(树上的点权第k大)

    Count on a tree Time Limit: 129MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Submi ...

  4. 主席树学习笔记(静态区间第k大)

    题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输出 ...

  5. 【bzoj3123】[Sdoi2013]森林 倍增LCA+主席树+启发式合并

    题目描述 输入 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负 ...

  6. CodeForces - 840D:(主席树求出现区间出现次数大于某值的最小数)

    Once, Leha found in the left pocket an array consisting of n integers, and in the right pocket q que ...

  7. 少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小

    少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小 有一道题(BZOJ 1901)是这样的:n个数,m个询问,询问有两种:修改某个数/询问区间第k小. 不带修改的区间第k小用主席树很好写 ...

  8. BZOJ2588:LCA+主席树来实现树上两点之间第K大点权查询

    对于每个节点维护这个节点到根的权值线段树 对于每个询问(x,y),这条路径上的线段树 tree[x]+tree[y]-tree[lca(x,y)]-tree[fa[lca(x,y)]] #includ ...

  9. UVALive - 7831 :ACM Tax (主席树求树路径上中位数:LCA+主席树)

    题意:给定一棵带权树,Q次询问,每次询问路径上的中位数. 思路:中位数分边数奇偶考虑,当当边数为num=奇时,结果就算路径第num/2+1大,用主席树做即可... (做了几道比较难的主席树,都wa了. ...

随机推荐

  1. kafka基础四

    消费者消费过程(二) 消费组状态机:消息的产生存储消费看似是杂乱无章的,但万物都会遵循一定的规则成长,任何事物的发展都是有迹可循的. 开始消费组初始状态为Stable,经过第一次Rebalance之后 ...

  2. iOS组件化开发· 什么是组件化

    越来越多公司,开始了组件化,你还要等到什么时候...... 说到开发模式,我们最熟知的开发模式 MVC 或者最近比较热门的MVVM.但是我今天说的组件化的开发,其实MVC不是一类的.它其实是····· ...

  3. 将Android系统源码导入Android studio的方法

    Android源码目录结构如下: |-- Makefile|-- abi (applicationbinary interface,应用程序二进制接口,生成libgabi++.so相关库文件)|-- ...

  4. css布局两边固定中间自适应的四种方法

    第一种:左右侧采用浮动 中间采用margin-left 和 margin-right 方法. 代码如下: <div style="width:100%; margin:0 auto;& ...

  5. sublime快捷键mark

    Ctrl+D 选词 (反复按快捷键,即可继续向下同时选中下一个相同的文本进行同时编辑)Ctrl+G 跳转到相应的行Ctrl+J 合并行(已选择需要合并的多行时)Ctrl+L 选择整行(按住-继续选择下 ...

  6. vijos 1448 校门外的树 (不是05年普及组那题)

    描述 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:K=1,K=1,读入l.r表 ...

  7. 计算机图形学:贝塞尔曲线(Bezier Curve)

    计算机图形学:贝塞尔曲线(Bezier Curve) 贝塞尔能由贝塞尔样条组合而成,也可产生更高维的贝塞尔曲面.

  8. ArcMap所有Command GUID

    The information in this topic is useful if you're trying to programmatically find a built-in command ...

  9. ios坐标系统

    在写程序的时候发现,iOS下的坐标.位置很容易弄乱,特别是在不同的坐标系统中,必须完成弄明白一些概念才能做相应的变化,例如CoreImage和UIView的坐标系统就截然不同,一个是以屏幕的左上角为原 ...

  10. 通过工厂模式批量创建对象后调用其中方法 出现XXXis not a function()问题原因

    //通过工厂模式批量创建 function Computer(color,weight,logo){         var obj=new Object();         obj.color=c ...