题面

一棵以

1

1

1 为根的

N

N

N 个节点的有根树,

Q

Q

Q 次询问,每次问一个点

u

u

u 的

k

k

k 级兄弟有多少个(第

k

k

k 代祖先的第

k

k

k 代孩子),如果没有则输出 0

N

,

Q

1

0

6

N,Q\leq 10^6

N,Q≤106 。

题解

像这种一个 log 可过的题目就是拿来 O(n) 做的

狗狗有言:挺板的长链剖分。

我们用离线+长链剖分来解决第

k

k

k 代孩子的问题,每个链顶存一个数组,表示每一代孩子的个数,把轻儿子的链合并。这个是长链剖分的常有操作,总共复杂度

O

(

n

)

O(n)

O(n) 。

如何

O

(

1

)

O(1)

O(1) 找

k

k

k 级祖先,这个很简单,不必用倍增。只需要把询问挂到树上,然后

d

f

s

\rm dfs

dfs 临时用一个数组栈存祖先就行了。

CODE

唉,又水了一篇

全程不用 vector ,常数极小

  1. #include<set>
  2. #include<map>
  3. #include<stack>
  4. #include<cmath>
  5. #include<ctime>
  6. #include<queue>
  7. #include<bitset>
  8. #include<cstdio>
  9. #include<cstring>
  10. #include<iostream>
  11. #include<algorithm>
  12. using namespace std;
  13. #define MAXN 1000005
  14. #define LL long long
  15. #define DB double
  16. #define ENDL putchar('\n')
  17. #define lowbit(x) (-(x) & (x))
  18. #define FI first
  19. #define SE second
  20. #define eps (1e-4)
  21. LL read() {
  22. LL f=1,x=0;char s = getchar();
  23. while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
  24. while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
  25. return f*x;
  26. }
  27. void putpos(LL x) {
  28. if(!x) return ;
  29. putpos(x/10); putchar('0'+(x%10));
  30. }
  31. void putnum(LL x) {
  32. if(!x) putchar('0');
  33. else if(x < 0) putchar('-'),putpos(-x);
  34. else putpos(x);
  35. }
  36. const int MOD = 1000000007;
  37. int n,m,s,o,k;
  38. int hd[MAXN],v[MAXN],nx[MAXN],cnt;
  39. void ins(int x,int y) {
  40. v[++ cnt] = y; nx[cnt] = hd[x];
  41. hd[x] = cnt; return ;
  42. }
  43. int d[MAXN],le[MAXN],son[MAXN];
  44. int hd2[MAXN],nx2[MAXN];
  45. int U[MAXN],kk[MAXN],fa[MAXN],as[MAXN];
  46. int st[MAXN],tp;
  47. int ar[MAXN<<1],he[MAXN],CN;
  48. void dfs0(int x,int ff) {
  49. d[x] = d[ff] + 1;
  50. st[++ tp] = x;
  51. for(int i = hd2[x];i;i = nx2[i]) {
  52. if(kk[i] >= d[x]) fa[i] = 0;
  53. else fa[i] = st[tp-kk[i]];
  54. }
  55. hd2[x] = 0;
  56. for(int i = hd[x];i;i = nx[i]) {
  57. dfs0(v[i],x);
  58. le[x] = max(le[x],le[v[i]] + 1);
  59. if(le[v[i]] >= le[son[x]]) son[x] = v[i];
  60. }
  61. tp --;
  62. return ;
  63. }
  64. void dfs(int x,int ff) {
  65. he[x] = ++ CN;
  66. ar[he[x]] ++;
  67. if(son[x]) dfs(son[x],x);
  68. for(int i = hd[x];i;i = nx[i]) {
  69. if(v[i] != son[x]) {
  70. dfs(v[i],x);
  71. for(int j = 0;j <= le[v[i]];j ++) {
  72. ar[he[x]+j+1] += ar[he[v[i]]+j];
  73. }
  74. }
  75. }
  76. for(int i = hd2[x];i;i = nx2[i]) {
  77. int le = d[U[i]] - d[x];
  78. as[i] = ar[he[x]+le] - 1;
  79. }
  80. return ;
  81. }
  82. int main() {
  83. n = read();m = read();
  84. for(int i = 2;i <= n;i ++) {
  85. s = read();o = i;
  86. ins(s,o);
  87. }
  88. for(int i = 1;i <= m;i ++) {
  89. U[i] = s = read();kk[i] = read();
  90. nx2[i] = hd2[s]; hd2[s] = i;
  91. }
  92. dfs0(1,0);
  93. for(int i = 1;i <= m;i ++) {
  94. if(!fa[i]) continue;
  95. nx2[i] = hd2[fa[i]]; hd2[fa[i]] = i;
  96. }
  97. dfs(1,0);
  98. for(int i = 1;i <= m;i ++) {
  99. putnum(as[i]);
  100. if(i < m) putchar(' ');
  101. }ENDL;
  102. return 0;
  103. }

P5384[Cnoi2019]雪松果树 (长链剖分)的更多相关文章

  1. [LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分

    题目链接: [JOI 2019 Final]独特的城市 对于每个点,它的答案最大就是与它距离最远的点的距离. 而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案. ...

  2. LOJ3053 十二省联考2019 希望 容斥、树形DP、长链剖分

    传送门 官方题解其实讲的挺清楚了,就是锅有点多-- 一些有启发性的部分分 L=N 一个经典(反正我是不会)的容斥:最后的答案=对于每个点能够以它作为集合点的方案数-对于每条边能够以其两个端点作为集合点 ...

  3. BZOJ 3653: 谈笑风生(离线, 长链剖分, 后缀和)

    题意 给你一颗有 \(n\) 个点并且以 \(1\) 为根的树.共有 \(q\) 次询问,每次询问两个参数 \(p, k\) .询问有多少对点 \((p, a, b)\) 满足 \(p,a,b\) 为 ...

  4. 2019.03.11 COGS2652 秘术(天文密葬法)(分数规划+长链剖分)

    传送门 题意:nnn个点的树,每个点两个值a,ba,ba,b,问长度为mmm的路径∑ai∑bi\frac{\sum a_i}{\sum b_i}∑bi​∑ai​​的最大值. 思路:一眼要01分数规划, ...

  5. 【BZOJ3522】【BZOJ4543】【POI2014】Hotel 树形DP 长链剖分 启发式合并

    题目大意 ​ 给你一棵树,求有多少个组点满足\(x\neq y,x\neq z,y\neq z,dist_{x,y}=dist_{x,z}=dist_{y,z}\) ​ \(1\leq n\leq 1 ...

  6. 【Vijos】lxhgww的奇思妙想(长链剖分)

    题面 给定一棵树,每次询问一个点的\(k\)次祖先,强制在线. Vijos 题解 长链剖分. 链接暂时咕咕咕了. 现在可以戳链接看题解了 #include<iostream> #inclu ...

  7. 【BZOJ4543】Hotel加强版(长链剖分)

    [BZOJ4543]Hotel加强版(长链剖分) 题面 BZOJ,没有题面 洛谷,只是普通版本 题解 原来我们的\(O(n^2)\)做法是设\(f[i][j]\)表示以\(i\)为根的子树中,距离\( ...

  8. 【BZOJ3653】谈笑风生(长链剖分)

    [BZOJ3653]谈笑风生(长链剖分) 题面 BZOJ 洛谷 权限题啊.... 题解 首先根据题目给的条件,发现\(a,b\)都要是\(c\)的父亲. 所以这三个点是树上的一条深度单增的链. 因为\ ...

  9. 【CF1009F】Dominant Indices(长链剖分)

    [CF1009F]Dominant Indices(长链剖分) 题面 洛谷 CF 翻译: 给定一棵\(n\)个点,以\(1\)号点为根的有根树. 对于每个点,回答在它子树中, 假设距离它为\(d\)的 ...

随机推荐

  1. B 树的简单认识

    理解 B 树的概念 B 树是一种自平衡的查找树,能够保持数据有序.这种数据结构能够让查找数据.顺序访问.插入数据及删除数据的动作,都能在对数时间内完成. 同一般的二叉查找树不同,B 树是一棵多路平衡查 ...

  2. Linux免密登陆配置(互信配置)

    Linux免密登陆配置(互信配置) 1.生成当前用户的秘钥文件 [oracle@localhost .ssh]$ ssh-keygen -t rsa 2.配置远程登录用户的公钥文件 将公钥文件拷贝至另 ...

  3. 2022年最强八股文《码出八股文-斩出offer线》

    宝剑锋从磨砺出,梅花香自苦寒来,大家好,我是小码哥 整理好的八股文终于完成了,希望看完对大家面试有所收获! 目录: 基础篇 javaOOP面试题 java集合/泛型面试题 java异常面试题 java ...

  4. nginx启动失败/报错(bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket...permissions) nginx启动失败

    出现这个问题是因为80端口被占用了 1.cmd输入命令netstat -aon|findstr "80" 2..查看80端口 16356对应的任务 输入命令 tasklist|fi ...

  5. MySQL进行 批量插入,批量删除,批量更新,批量查询

    1.批量插入 ServiceImpl层 List<Person> addPeople = new ArrayList<>(); //addPeople存放多个Person对象 ...

  6. 记一次重复造轮子(Obsidian 插件设置说明汉化)

    杂谈 #Java脚本 因本人英语不好在使用Obsidian时,一些插件的设置英文多令人头痛.故有写一个的翻译插件介绍和设置脚本的想法.看到有些前人写的一下翻译方法,简直惨目忍睹.竟然要手动.这个应该写 ...

  7. string的底层实现

    String底层实现 string在C++也是一个重要的知识,但是想要用好它,就要知道它的底层是如何写的,才能更好的用好这个string,那么这次就来实现string的底层,但是string的接口功能 ...

  8. 绝对路径-相对路径和File类的构造方法

    绝对路径和相对路径 绝对路径:是一个完整的路径,以盘符开始(c: d:)c:\a.txt 相对路径:相对指的是相对于当前项目的根目录(可以省略项目的根目录) 注意: 1.路径不区分大小写 2.路径中的 ...

  9. throw关键字和Objects非空判断_requireNonNull方法

    作用: 可以使用throw关键字在指定的方法中抛出指定的异常 使用格式: throw new xxxException("异常产生的原因") 注意: 1.throw关键字必须写在方 ...

  10. dolphinscheduler添加hana支持

    dolphinscheduler添加hana支持 转载请注明出处: https://www.cnblogs.com/funnyzpc/p/16395092.html 前面 上一节有讲datax对han ...