P5903 【模板】树上 k 级祖先
学习笔记:https://www.luogu.com.cn/blog/Ynoi/zhang-lian-pou-fen-xue-xi-bi-ji
题解:
https://www.luogu.com.cn/blog/_post/204460
https://www.luogu.com.cn/blog/b6e0/tijie-P5903#
code:
#include<bits/stdc++.h>
using namespace std;
#define MN 500005
int n,m,u,v,cnt,fa[MN],siz[MN],w[MN],top[MN],dep[MN],id[MN],ID[MN];
vector<int>edge[MN];
void dfs1(int x){
siz[x]=1;
for(int i=0;i<edge[x].size();++i){
fa[edge[x][i]]=x;
dep[edge[x][i]]=dep[x]+1;
dfs1(edge[x][i]);
siz[x]+=siz[edge[x][i]];
if(siz[w[x]]<siz[edge[x][i]])w[x]=edge[x][i];
}
}
void dfs2(int x){
id[x]=++cnt;
ID[cnt]=x;
if(w[x]){top[w[x]]=top[x];dfs2(w[x]);}
for(int i=0;i<edge[x].size();++i)
if(edge[x][i]!=w[x]){
top[edge[x][i]]=edge[x][i];
dfs2(edge[x][i]);
}
}
int rt;
int jump(int x,int k){
while(k >= id[x]-id[top[x]]+1 && x!=rt){ //根结点
k -= (id[x]-id[top[x]]+1);
x = fa[top[x]];
}
return ID[id[x]-k];//如果一旦小于,则说明在重链上,线段树上就是连续的一段
}
#define ui unsigned int
ui S;
#define LL long long
inline ui get(ui x) {
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
return S = x;
}
int main(){
n=read();m=read();scanf("%u",&S);
rt=1;
for(int i=1;i<=n;++i){
fa[i]=read();
if(!fa[i])rt=i;
else edge[fa[i]].push_back(i);
}
dep[rt]=1;dfs1(rt);
top[rt]=rt;dfs2(rt);
LL ans=0;
int lstans=0;
for(int i=1;i<=m;++i){
int x=(get(S)^lstans)%n+1;
int k=(get(S)^lstans)%dep[x];
lstans=jump(x,k);//返回这个k级祖先
ans^=(LL)i*lstans;
}
printf("%lld\n",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架