【模板】树上 k 级祖先

题目链接:luogu P5903

题目大意

给你一棵树,要你在线 O(1) 求一个点的 k 级祖先。

思路

这个我们可以用长链剖分来做,从而可以做到预处理 O ( n log ⁡ n ) O(n\log n) O(nlogn) 询问 O ( 1 ) O(1) O(1)。

首先预处理:
最数进行长链剖分(就是找最长的一条链,可以通过深度来看),也是记录对应儿子。( O ( n ) O(n) O(n))
然后倍增求 2 k 2^k 2k 级父亲。( O ( n log ⁡ n ) O(n\log n) O(nlogn))
然后每条长链,如果长度为 l e n len len,我们就求出从它的顶点出发,它向上的 l e n len len 个祖先和向下走长链的 l e n len len 个儿子。( O ( n ) O(n) O(n))
然后再求每个数二进制最高位 g k g_k gk​。( O ( n ) O(n) O(n))

然后看询问怎么回答:
首先用倍增数组跳到 k k k 的最高位级父亲,那假设剩下 k ′ k' k′ 级,那首先由 k ′ < 2 g k k'<2^{g_k} k′<2gk​,而且因为是长链,所以 x x x 所在的长链的长度一定 ⩾ 2 g k > k ′ \geqslant 2^{g_k}>k' ⩾2gk​>k′。
那根据 l e n len len(长链长度) > k ′ >k' >k′,所以我们可以跳到链的顶点,然后看 k ′ − l e n = k ′ ′ k'-len=k'' k′−len=k′′:
如果 k ′ ′ > 0 k''>0 k′′>0,说明要的点还在上面,就用上面的。
如果 k ′ ′ < 0 k''<0 k′′<0,说明要的点在下面,就用下面的。
(这两个就是 n log ⁡ n n\log n nlogn 预处理出来的那个)

然后就可以了。

代码

#include<cstdio>
#include<vector>
#define ll long longusing namespace std;const int N = 5e5 + 100;
int n, q, f[N][21], rt, lstans;
int deg[N], d[N], son[N], top[N], g[N];
vector <int> G[N], up[N], down[N];
ll ans;#define ui unsigned int
ui s;inline ui get(ui x) {x ^= x << 13;x ^= x >> 17;x ^= x << 5;return s = x;
}void dfs0(int now, int father) {d[now] = d[father] + 1; deg[now] = d[now];for (int i = 1; i <= 20; i++) f[now][i] = f[f[now][i - 1]][i - 1];for (int i = 0; i < G[now].size(); i++) {int x = G[now][i]; dfs0(x, now);if (deg[x] > deg[now]) deg[now] = deg[x], son[now] = x;}
}void dfs1(int now, int father) {if (now == top[now]) {for (int i = 0, x = now; i <= deg[now] - d[now]; i++)up[now].push_back(x), x = f[x][0];for (int i = 0, x = now; i <= deg[now] - d[now]; i++)down[now].push_back(x), x = son[x];}if (son[now]) top[son[now]] = top[now], dfs1(son[now], now);for (int i = 0; i < G[now].size(); i++) {int x = G[now][i]; if (x == son[now]) continue;top[x] = x; dfs1(x, now);}
}int Jump(int x, int k) {if (!k) return x;x = f[x][g[k]]; k -= (1 << g[k]);//先跳最高的 1k -= d[x] - d[top[x]]; x = top[x];//跳到这个长链的顶部return k >= 0 ? up[x][k] : down[x][-k];//直接找
}int main() {scanf("%d %d %u", &n, &q, &s); g[0] = -1;for (int i = 1; i <= n; i++) {scanf("%d", &f[i][0]); if (!f[i][0]) rt = i;G[f[i][0]].push_back(i); g[i] = g[i >> 1] + 1;}dfs0(rt, 0); top[rt] = rt; dfs1(rt, 0);for (int qq = 1; qq <= q; qq++) {int x = ((get(s) ^ lstans) % n) + 1, k = (get(s) ^ lstans) % d[x];lstans = Jump(x, k); ans ^= 1ll * qq * lstans;}printf("%lld", ans);return 0;
}

【luogu P5903】【模板】树上 k 级祖先(长链剖分)相关推荐

  1. UOJ284 快乐游戏鸡(树上动态规划问题、长链剖分+单调栈)

    Description 一棵 n 个点的有根树,带点权 wi. 从 s 出发,希望达到 t,每秒可以从当前点移动到某一个儿子. 有一个死亡次数,初始为 0.若在某个点 i(i != s, t) 时,死 ...

  2. Blood Cousins (dsu on tree + 求第k级祖先)

    题目链接: Blood Cousins 大致题意 给出一片森林, 询问对于给定的点而言, 其k级祖先中有多少个点的深度和当前节点相同. 解题思路 dsu on tree 对于每个询问x, k而言, 我 ...

  3. 对LCA、树上倍增、树链剖分(重链剖分长链剖分)和LCT(Link-Cut Tree)的学习

    LCA what is LCA & what can LCA do LCA(Lowest Common Ancestors),即最近公共祖先 在一棵树上,两个节点的深度最浅的公共祖先就是 L ...

  4. 长链剖分:O(nlogn)预处理O(1)求kth祖先

    前言 一个长链剖分的小trick 问题 如题,数据范围大概10510^5105 思路 我们知道重链剖分是什么,即选择自己儿子中子树节点树最大的作为重儿子,其它儿子为轻儿子 而长链剖分则是选择儿子中子树 ...

  5. 【UOJ#33】【UR #2】树上GCD(长链剖分/根号分类讨论)

    [UOJ#33][UR #2]树上GCD 求解树上两个点到lca的距离的最大公约数是k的对数 首先我们很容易就想到莫比乌斯反演,那么利用倍数形式,我们只需要求解是i的倍数的对数. 考虑枚举lca,这个 ...

  6. 【luogu CF1009F】Dominant Indices(长链剖分优化DP)

    Dominant Indices 题目链接:luogu CF1009F 题目大意 给你一棵以 1 为根的树,设 d(u,x) 为 u 子树总到 u 距离为 x 的点数. 然后要你对于每个点 x 都要求 ...

  7. UOJ#33-[UR #2]树上GCD【长链剖分,根号分治】

    正题 题目链接:https://uoj.ac/problem/33 题目大意 给出nnn个点的一棵树 定义f(x,y)=gcd(dis(x,lca),dis(y,lca))f(x,y)=gcd(\ d ...

  8. 长链剖分优化树形dp

    apio铁牌告辞(开场想打暴力然后gedit码代码5个小时没写完三题最低档暴力真是快乐),听课也就学到了一丢丢这个东西. 模板题: https://www.luogu.org/problemnew/s ...

  9. BZOJ4381[POI2015]Odwiedziny——分块+长链剖分

    题目描述 给定一棵n个点的树,树上每条边的长度都为1,第i个点的权值为a[i]. Byteasar想要走遍这整棵树,他会按照某个1到n的全排列b走n-1次,第i次他会从b[i]点走到b[i+1]点,并 ...

最新文章

  1. iOS动画开发----打分 数字滚动刷新动画
  2. 设计模式复习-模板方法模式
  3. 盘点上班族和大学生都适用的8个赚外快的小方法 总有一个适合你
  4. java-静态-单例-继承
  5. Java变量名的命名方式
  6. 4_less中带参数混合
  7. mysql一对多增删改查_SQLAlchemy 增删改查 一对多 多对多
  8. Java常见概念(POJO\javabean\DTO\PO\BO\VO)浅析
  9. 凸优化第四章凸优化问题 4.6 广义不等式约束
  10. 最好用的HDR图像处理器——Photomatix Pro新功能介绍及使用教程
  11. 零基础自学Java要多久,是不是很难?
  12. 如何把后缀为.mdf的文件打开
  13. 数据库维护任务-邮件通知:未配置全局配置文件。请在 @profile_name 参数中指定配置文件名。
  14. OS学习笔记-1(清华大学慕课)操作系统概述
  15. 不安全的文件上传基本原理(Unsafe file upload)
  16. ContentProvider详解
  17. private和protected的区别
  18. Word突然不能复制粘贴怎么办?
  19. 用python制作微信机器人程序编写_Python制作微信聊天机器人
  20. (原创)LEON3入门教程(三):基于LEON3的SOPC设计以及HELLOWORLD和流水灯

热门文章

  1. 19.overflow属性设置溢出内容
  2. 2015年10月11日
  3. C#与PLC通信开发之西门子s7-200 smart
  4. Simulink 自动代码生成原理
  5. Python模拟登陆新浪微博,爬取用户数据
  6. 客户价值分析(聚类)--【Excel+SPSS】和python实现
  7. 智能化嵌入式软件测试平台总体介绍
  8. 虚幻四Gameplay Ability System入门(9)-神罗天征!TargetActor
  9. c语言readline库6,GNU Readline Library编译及简单分析
  10. only batches of spatial targets supported (3D tensors) but got targets of dimension