树上 k 级祖先非长剖做法
预处理倍增链顶复杂度 。
类似 LCA 跳就好了。
参考 @YLWang
#include <bits/stdc++.h>
#define int long long
using namespace std;
template <typename T> inline void read(T &x) {
x = 0; char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
}
const int N = 5e5 + 10;
int n, q, s, idx, fa[N], dep[N], siz[N];
int rt, dfn[N], id[N], tp[N][6];
vector <int> G[N];
inline void dfs1(int cur, int f) {
fa[cur] = f, dep[cur] = dep[f] + 1, siz[cur] = 1;
for (auto to: G[cur])
dfs1(to, cur), siz[cur] += siz[to];
return ;
}
inline void dfs2(int cur, int Tp) {
int heavyson = 0; dfn[cur] = ++idx;
id[idx] = cur, tp[cur][0] = Tp;
for (int i = 1; i < 5; ++i)
tp[cur][i] = tp[fa[tp[cur][i - 1]]][i - 1];
for (auto to: G[cur])
if (siz[to] > siz[heavyson]) heavyson = to;
if (!heavyson) return ; dfs2(heavyson, Tp);
for (auto to: G[cur])
if (to != fa[cur] && to != heavyson) dfs2(to, to);
return ;
}
inline int kth(int cur, int k) {
for (int i = 4; ~i; --i)
if (tp[cur][i] && k > dep[cur] - dep[tp[cur][i]])
k -= dep[cur] - dep[tp[cur][i]] + 1, cur = fa[tp[cur][i]];
if (!cur) return 0;
// cout << "ID:" << id[dfn[cur] - k] << endl;
return id[dfn[cur] - k];
}
inline int get(unsigned x) {
x ^= x << 13, x ^= x >> 17;
x ^= x << 5; return s = (int)x;
}
signed main() {
read(n), read(q), read(s);
for (int i = 1; i <= n; ++i) {
int f; read(f); if (!f) { rt = i; continue; }
G[f].emplace_back(i);
}
dfs1(rt, 0), dfs2(rt, rt);
int ans = 0, res = 0;
for (int i = 1; i <= q; ++i) {
int cur = (get(s) ^ ans) % n + 1;
int k = (get(s) ^ ans) % dep[cur];
ans = kth(cur, k); res ^= (i * ans);
}
cout << res << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现