题目大意:给定一棵 N 个节点的树,点有点权,要求回答 M 个询问,每次询问点 u 到点 v 的简单路径(链)上权值第 K 小是多少。

题解:学习到了树上主席树。

主席树维护序列时,每次将后一个点的树建立在前一个点的树上,由此构成一个前缀和,并利用可以在线段树上二分的性质来求 K 小值。树上主席树维护的是每个节点到根节点路径上的前缀和,即:每个点的主席树建立在其父节点的主席树基础上。回答答案时,只需在 u,v,lca(u,v),fa[lca(u,v)] 的四棵主席树上面二分答案即可。

代码如下

  1. #include <cstdio>
  2. #include <algorithm>
  3. using namespace std;
  4. const int maxn=1e5+10;
  5. int n,m,val[maxn],d[maxn],len;
  6. int f[maxn][21],dep[maxn];
  7. struct Graph{
  8. int nxt,to;
  9. }e[maxn<<1];
  10. int tot=1,head[maxn];
  11. inline void add_edge(int from,int to){
  12. e[++tot]=(Graph){head[from],to},head[from]=tot;
  13. }
  14. struct node{
  15. #define ls(x) t[x].lc
  16. #define rs(x) t[x].rc
  17. int lc,rc,sum;
  18. }t[maxn*20];
  19. int cnt,root[maxn];
  20. inline void pushup(int o){t[o].sum=t[ls(o)].sum+t[rs(o)].sum;}
  21. int insert(int pre,int l,int r,int pos,int value){
  22. int o=++cnt;
  23. t[o]=t[pre];
  24. if(l==r){t[o].sum+=value;return o;}
  25. int mid=l+r>>1;
  26. if(pos<=mid)ls(o)=insert(ls(pre),l,mid,pos,value);
  27. else rs(o)=insert(rs(pre),mid+1,r,pos,value);
  28. return pushup(o),o;
  29. }
  30. int query(int a,int b,int c,int d,int l,int r,int k){
  31. if(l==r)return l;
  32. int mid=l+r>>1;
  33. int sum=t[ls(c)].sum+t[ls(d)].sum-t[ls(a)].sum-t[ls(b)].sum;
  34. if(k<=sum)return query(ls(a),ls(b),ls(c),ls(d),l,mid,k);
  35. else return query(rs(a),rs(b),rs(c),rs(d),mid+1,r,k-sum);
  36. }
  37. inline int ask(int x){return lower_bound(d+1,d+len+1,x)-d;}
  38. void read_and_parse(){
  39. scanf("%d%d",&n,&m);
  40. for(int i=1;i<=n;i++)scanf("%d",&val[i]),d[++len]=val[i];
  41. for(int i=1,x,y;i<n;i++){
  42. scanf("%d%d",&x,&y);
  43. add_edge(x,y),add_edge(y,x);
  44. }
  45. sort(d+1,d+len+1);
  46. len=unique(d+1,d+len+1)-d-1;
  47. }
  48. void dfs(int u,int fa){
  49. dep[u]=dep[fa]+1,f[u][0]=fa;
  50. for(int i=1;i<=20;i++)f[u][i]=f[f[u][i-1]][i-1];
  51. root[u]=insert(root[fa],1,len,ask(val[u]),1);
  52. for(int i=head[u];i;i=e[i].nxt){
  53. int v=e[i].to;if(v==fa)continue;
  54. dfs(v,u);
  55. }
  56. }
  57. int lca(int x,int y){
  58. if(dep[x]<dep[y])swap(x,y);
  59. for(int i=18;~i;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i];
  60. if(x==y)return x;
  61. for(int i=18;~i;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
  62. return f[x][0];
  63. }
  64. void solve(){
  65. int lastans=0;
  66. dfs(1,0);
  67. while(m--){
  68. int x,y,k;
  69. scanf("%d%d%d",&x,&y,&k);
  70. x=lastans^x;
  71. int z=lca(x,y);
  72. printf("%d\n",lastans=d[query(root[f[z][0]],root[z],root[x],root[y],1,len,k)]);
  73. }
  74. }
  75. int main(){
  76. read_and_parse();
  77. solve();
  78. return 0;
  79. }

【SPOJ10628】Count on a tree的更多相关文章

  1. 【BZOJ2588】Count On a Tree(主席树)

    [BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...

  2. 【SPOJ】Count On A Tree II(树上莫队)

    [SPOJ]Count On A Tree II(树上莫队) 题面 洛谷 Vjudge 洛谷上有翻译啦 题解 如果不在树上就是一个很裸很裸的莫队 现在在树上,就是一个很裸很裸的树上莫队啦. #incl ...

  3. 【BZOJ-2588】Count on a tree 主席树 + 倍增

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 3749  Solved: 873[ ...

  4. 【BZOJ2558】Count on a tree

    又是因为傻逼错误浪费了半天时间 原题: 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个 ...

  5. 【bzoj2588】Count on a tree

    Portal -->bzoj2588 Solution 不行我一定要来挂这道题qwq很气愤qwq(其实还不是因为自己蠢..) 额首先说一下正解 如果这个问题放在序列上面的话..直接离散化一下然后 ...

  6. 【bzoj2588】Count on a tree 主席树

    这题给人开了个新思路. 原本构造一个序列的主席树,是这个位置用上个位置的信息来省空间,树上的主席树是继承父亲的信息来省空间. 此题若带修改怎么办? 若对某个点的权值做修改,则这个点的子树都会受影响,想 ...

  7. 【BZOJ2588】Count on a tree 题解(主席树+LCA)

    前言:其实就是主席树板子啦……只不过变成了树上的查询 -------------------------- 题目链接 题目大意:求树上$u$到$v$路径第$k$大数. 查询静态区间第$k$大肯定是用主 ...

  8. 【数据挖掘】分类之decision tree(转载)

    [数据挖掘]分类之decision tree. 1. ID3 算法 ID3 算法是一种典型的决策树(decision tree)算法,C4.5, CART都是在其基础上发展而来.决策树的叶子节点表示类 ...

  9. 【LeetCode】二叉查找树 binary search tree(共14题)

    链接:https://leetcode.com/tag/binary-search-tree/ [220]Contains Duplicate III (2019年4月20日) (好题) Given ...

随机推荐

  1. Individual Project - Word_frequency

    0x00 预先准备和时间规划 1.因为要用到visual studio 2013,准备学习C#,预计一天时间能基本使用. 3.了解需求并设计基本数据结构与大致流程 20min 2.根据提议实现simp ...

  2. "Linux内核分析"第七周

    可执行程序的装载 张文俊+原创作品转载请注明出处+<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.预 ...

  3. 《Linux内核设计与实现》读书笔记 18

    第十八章调试 18.1 准备开始 一个bug:大部分bug通常都不是行为可靠而且定义明确的 一个藏匿bug的内核版本:找出bug首先出现的版本 相关内核代码的知识和运气 18.2内核中的bug 可以有 ...

  4. 关于五子棋游戏java版

    一 题目简介:关于五子棋游戏 二 源码的github链接   https://github.com/marry1234/test/blob/master/五子棋游戏 三.所设计的模块测试用例.测试结果 ...

  5. mybaits拦截器+自定义注解

    实现目的:为了存储了公共字典表主键的其他表在查询的时候不用关联查询(所以拦截位置位于mybaits语句查询得出结果集后) 项目环境 :springboot+mybaits 实现步骤:自定义注解——自定 ...

  6. C程序设计教学小结(选择结构)

    1. 函数使用的三个问题 函数声明语句   void add();   或  int add(int x,int y); 函数调用            add();     c=add(a,b) 函 ...

  7. SpringMVC运行流称总结(DispatcherServlet-doDispatch)

    1.运行流程 1).所有请求都是由前端控制器处理: 2).请求路径和RequestMapping进行对比, 3).找到就直接利用反射调用方法 4).把方法返回值作为页面地址,直接转发到这个页面: 四步 ...

  8. 量产救U盘

    同事U盘不能格式化,快速格式化失败,非快速格式化也失败.就问谁有360安全软件,试试能不能格式化. 我说我有火绒,但是不知道火绒并没有格式化U盘的功能(应该没有吧,反正我找了以后没找到) 那怎么办呢? ...

  9. opencv学习笔记(四)

    ROI---设定感兴趣的区域(region of interest) 定义: Mat imageROI; //方法一:通过Rect指定矩形区域 imageROI=image(Rect(500,250, ...

  10. 安装phpredis扩展

    本文是根据菜鸟教程中的内容而写的,因为按照教程中做法来操作,中间遇到一些问题,我在centos6.5和ubuntu16.4中都遇到了,所以写在这里.强烈建议你先看完这篇博客,然后再操作,能省不少事. ...