题目链接:https://www.spoj.com/problems/COT/en/

题意:求树上A,B两点路径上第K小的数

思路:主席树实际上是维护的一个前缀和,而前缀和不一定要出现在一个线性表上。

比如说我们从一棵树的根节点进行DFS,得到根节点到各节点的距离dist[x]——这是一个根-x路径上点与根节点距离的前缀和。

利用这个前缀和,我们可以解决一些树上任意路径的问题,比如在线询问[a,b]点对的距离——答案自然是dist[a]+dist[b]-2*dist[lca(a,b)]。

DFS遍历整棵树,然后在每个节点上建立一棵线段树,某一棵线段树的“前一版本”是位于该节点父亲节点fa的线段树。

利用与之前类似的方法插入点权(排序离散)。那么对于询问[a,b],答案就是root[a]+root[b]-root[lca(a,b)]-root[fa[lca(a,b)]]上的第k大。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<queue>
  4. #include<cmath>
  5. #include<algorithm>
  6. #include<map>
  7. #include<vector>
  8. #include<string>
  9. #include<set>
  10. #define ll long long
  11. #define maxn 100007
  12. using namespace std;
  13. const int MAXN=1e5+;
  14. const int POW=;
  15. int num[MAXN],node[MAXN];
  16. struct point
  17. {
  18. int l;
  19. int r;
  20. int sum;
  21. }T[MAXN*];
  22. int root[MAXN];
  23. vector<int> G[MAXN];
  24. int d[MAXN];
  25. int p[MAXN][POW];
  26. int tot;
  27. int f[MAXN];
  28. int n,m;
  29. void build(int l,int r,int& rt)
  30. {
  31. rt=++tot;
  32. T[rt].sum=;
  33. if(l>=r)return;
  34. int m=(l+r)>>;
  35. build(l,m,T[rt].l);
  36. build(m+,r,T[rt].r);
  37. }
  38. void update(int last,int p,int l,int r,int &rt)
  39. {
  40. rt=++tot;
  41. T[rt].l=T[last].l;
  42. T[rt].r=T[last].r;
  43. T[rt].sum=T[last].sum+;
  44. if(l>=r)return ;
  45. int m=(l+r)>>;
  46. if(p<=m)update(T[last].l,p,l,m,T[rt].l);
  47. else update(T[last].r,p,m+,r,T[rt].r);
  48. }
  49. int query(int left_rt,int right_rt,int lca_rt,int lca_frt,int l,int r,int k)
  50. {
  51. if(l>=r)return l;
  52. int m=(l+r)>>;
  53. int cnt=T[T[right_rt].l].sum+T[T[left_rt].l].sum-T[T[lca_rt].l].sum-T[T[lca_frt].l].sum;
  54. if(k<=cnt)
  55. return query(T[left_rt].l,T[right_rt].l,T[lca_rt].l,T[lca_frt].l,l,m,k);
  56. else
  57. return query(T[left_rt].r,T[right_rt].r,T[lca_rt].r,T[lca_frt].r,m+,r,k-cnt);
  58. }
  59. void dfs(int u,int fa,int cnt)
  60. {
  61. f[u]=fa;
  62. d[u]=d[fa]+;
  63. p[u][]=fa;
  64. for(int i=;i<POW;i++)
  65. p[u][i]=p[p[u][i-]][i-];
  66. update(root[fa],num[u],,cnt,root[u]);
  67. for(int i=;i<(int)G[u].size();i++)
  68. {
  69. int v=G[u][i];
  70. if(v==fa)continue;
  71. dfs(v,u,cnt);
  72. }
  73. }
  74. int lca(int a,int b)
  75. {
  76. if(d[a]>d[b])
  77. a^=b,b^=a,a^=b;
  78. if(d[a]<d[b])
  79. {
  80. int del=d[b]-d[a];
  81. for(int i=;i<POW;i++)
  82. if(del&(<<i))b=p[b][i];
  83. }
  84. if(a!=b)
  85. {
  86. for(int i=POW-;i>=;i--)
  87. {
  88. if(p[a][i]!=p[b][i])
  89. {
  90. a=p[a][i],b=p[b][i];
  91. }
  92. }
  93. a=p[a][],b=p[b][];
  94. }
  95. return a;
  96. }
  97. void init()
  98. {
  99. for(int i=;i<=n;i++)
  100. {
  101. G[i].clear();
  102. }
  103. memset(d,,sizeof(d));
  104. memset(p,,sizeof(p));
  105. memset(f,,sizeof(f));
  106. }
  107. int main()
  108. {
  109. while(~scanf("%d%d",&n,&m))
  110. {
  111. init();
  112. for(int i=;i<=n;i++)
  113. {
  114. scanf("%d",&num[i]);
  115. node[i]=num[i];
  116. }
  117. tot=;
  118. sort(node+,node++n);
  119. int cnt=unique(node+,node+n+)-node-;
  120. for(int i=;i<=n;i++)
  121. {
  122. num[i]=lower_bound(node+,node+cnt+,num[i])-node;
  123. }
  124. int a,b,c;
  125. for(int i=;i<=n-;i++)
  126. {
  127. scanf("%d%d",&a,&b);
  128. G[a].push_back(b);
  129. G[b].push_back(a);
  130. }
  131. build(,cnt,root[]);
  132. dfs(,,cnt );
  133. while(m--)
  134. {
  135. scanf("%d%d%d",&a,&b,&c);
  136. int t=lca(a,b);
  137. int id=query(root[a],root[b],root[t],root[f[t]],,cnt,c);
  138. printf("%d\n",node[id]);
  139. }
  140. }
  141. return ;
  142. }

Count on a tree(树上路径第K小)的更多相关文章

  1. Count on a tree 树上区间第K小

    Count on a tree 题意:求路径 u到v上的 第k小的权重. 题解:先DFS建数, 然后对于每个节点往上跑出一颗主席树, 然后每次更新. 查询的时候, u, v, k, 找到  z = l ...

  2. SPOJ-COT-Count on a tree(树上路径第K小,可持久化线段树)

    题意: 求树上A,B两点路径上第K小的数 分析: 同样是可持久化线段树,只是这一次我们用它来维护树上的信息. 我们之前已经知道,可持久化线段树实际上是维护的一个前缀和,而前缀和不一定要出现在一个线性表 ...

  3. Count on a tree 树上主席树

    Count on a tree 树上主席树 给\(n\)个树,每个点有点权,每次询问\(u,v\)路径上第\(k\)小点权,强制在线 求解区间静态第\(k\)小即用主席树. 树上主席树类似于区间上主席 ...

  4. POJ 1741 Tree 求树上路径小于k的点对个数)

                                                                                                 POJ 174 ...

  5. E - Count on a tree 树上第K小

    主席树的入门题目,这道题的题意其实就是说,给你一棵树,询问在两个节点之间的路径上的区间第K小 我们如何把树上问题转换为区间问题呢? 其实DFS就可以,我们按照DFS的顺序,对线段树进行建树,那么这个树 ...

  6. spoj COT - Count on a tree (树上第K小 LCA+主席树)

    链接: https://www.spoj.com/problems/COT/en/ 思路: 首先看到求两点之前的第k小很容易想到用主席树去写,但是主席树处理的是线性结构,而这道题要求的是树形结构,我们 ...

  7. BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 5217  Solved: 1233 ...

  8. BZOJ 2588: Spoj 10628. Count on a tree 树上跑主席树

    2588: Spoj 10628. Count on a tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/J ...

  9. Codeforces 739B Alyona and a tree(树上路径倍增及差分)

    题目链接 Alyona and a tree 比较考验我思维的一道好题. 首先,做一遍DFS预处理出$t[i][j]$和$d[i][j]$.$t[i][j]$表示从第$i$个节点到离他第$2^{j}$ ...

随机推荐

  1. IDEA中解决 git pull 冲突

    0.事先准备.1)把远程仓库的README.md内容改写为bbb(原先为aaa). 2)本地仓库的README.md内容改写为ccc(原先也为aaa). 以此来模仿代码冲突.    1.先commit ...

  2. ubuntu 安装企业级容器 docker harbor

    安装docker harbor 企业级容器   环境说明: 操作系统: ubuntu16.04.5 LTS IP地址:  192.168.31.129   https://github.com/goh ...

  3. 1000行基本SQL

    /* Windows服务 */ -- 启动MySQL net start mysql -- 创建Windows服务 sc create mysql binPath= mysqld_bin_path(注 ...

  4. oracle 实现mysql find_set_in函数

    create or replace FUNCTION F_FIND_IN_SET(piv_str1 varchar2, piv_str2 varchar2, p_sep varchar2 := ',' ...

  5. logstash启动时找不到自定义的JAVA_HOME环境变量

    logstash java 版本问题 配置logstash收集应用日志时出现报错,说是找不到JAVA_HOME环境变量,但是明明已经设置了 logstash要求java 1.8以上,查看生产环境: [ ...

  6. go & log

    更多日志库 https://github.com/golang/glog github.com/astaxie/beego/logs ... 这里有一个讨论 Golang的log包哪个好用? 参考 G ...

  7. Maven下载清除jar包

    maven jar包下载命令行方式 在STS中下载JAR包时经常卡住无法继续下载,这时可以用命令行方式进行下载.在终端中今入到该项目的根目录下,然后mvn clean;mvn install;等待下载 ...

  8. [七月挑选]IntelliJ IDEA常用设置

    title: IntelliJ IDEA常用设置 设置idea的类注释快捷键 File -> Settings -> Live Templates 1.右边的 + -> Templa ...

  9. order by关键字优化

    1.ORDER BY子句,尽量使用Index方式排序,避免使用FileSort方式排序 2.建表SQL CREATE TABLE tblA( id int primary key not null a ...

  10. Mongo--03 mongo副本集、备份与恢复

    目录 一.mongo副本集配置 二.查看副本集状态 三.副本集权重调整 四.创建节点 五.仲裁节点 六.mongo备份与恢复 七.准备测试数据 一.mongo副本集配置 1.创建节点目录和数据目录 # ...