Luogu P13019 [GESP202506 八级] 树上旅行 题解
首先,我们来分析一下题目中给出的两种移动方法:
- 移动至当前结点的父结点。特殊地,如果当前位于根结点,则不进行移动;
- 移动至当前结点的所有子结点中编号最小的结点。特殊地,如果当前位于叶子结点,则不进行移动。
预处理
不难发现,对于每个节点 \(i\) 来说,它最高能达到的节点一定是根节点 \(1\),最低能达到的节点同样是固定的。那么,我们不妨预处理一下 \(i\) 号节点的第 \(2^j\) 级祖先 \(f[i][j]\) 与其第 \(2^j\) 级子节点 \(son[i][j]\),当然 \(i\) 号节点的第 \(2^j\) 级子节点最多可能有 \(2^{j+1}\) 个,我们不可能维护 \(i\) 号节点的所有第 \(2^j\) 级子节点,所以我们只维护 \(i\) 号节点在第 \(2\) 种移动方式下会移动到的子节点,\(son[i][0]\) 维护的是 \(i\) 号节点的最小的一级子节点,\(son[i][1]\) 维护的是 \(son[i][0]\) 号节点的最小的一级子节点,\(son[i][2]\) 维护的是 \(son[i][1]\) 号节点的最小的二级子节点,以此类推
处理移动
接下来,让我们来处理移动,我们以向上移动 \(a_{i,j}\) 次为例,我们将当前位于节点 \(s\) 的深度 \(d[s]\) 减 \(a_{i,j}\),特判 \(d[s]\) 是否等于 \(1\),如果等于 \(1\),我们就将 \(d[s]\) 与 \(s\) 赋值为 \(1\),否则通过 \(f[s]\) 数组将 \(s\) 跳到这个深度。至于向下跳,我们只需注意将跳至 \(1\) 号根节点的特判改为跳至 \(son[s][18]\) 号最底层节点的特判,为什么 \(son[s][18]\) 就是最底层节点呢?因为我们可以将叶节点的 \(son[s][0]\) 记为 \(s\) 自己,这样由于 \(2^{18}=262144>100000=n\),那么在递归更新中 \(son[i][18]\) 一定会更新为 \(i\) 号节点的最底层节点。
最后的时间复杂度为 \(O(n+\log n(n+\displaystyle\sum^q_{i=1} k_i))\)
没想明白为什么不小心把向下跳更新 \(s\) 与向上跳更新 \(s\) 同时写成了向上跳更新 \(s\) 的函数后也是100pts(离谱)
code
#include<bits/stdc++.h>
using namespace std;
int n,q,f[100005][25],son[100005][25],d[100005],s,k;
priority_queue<int,vector<int>,greater<int> >e[100005];//通过优先队列维护小的子节点在前
void init(int x){//预处理
for(int i=1;i<=18;i++)
f[x][i]=f[f[x][i-1]][i-1];
bool f=true;
int id;
while(!e[x].empty()){
if(f){
son[x][0]=e[x].top();
f=false;
}
d[e[x].top()]=d[x]+1;
init(e[x].top());
e[x].pop();
}
if(!son[x][0])
son[x][0]=x;
for(int i=1;i<=18;i++)
son[x][i]=son[son[x][i-1]][i-1];
}
int down(int st,int de){
for(int i=18;i>=0;i--){
if(d[son[st][i]]<=de)
st=son[st][i];
}
return st;
}
int up(int st,int de){
for(int i=18;i>=0;i--){
if(d[f[st][i]]>=de)
st=f[st][i];
}
return st;
}
int main(){
cin>>n>>q;
for(int i=0;i<n-1;i++){
int x;
cin>>x;
e[x].push(i+2);
f[i+2][0]=x;
}
d[1]=1;
init(1);
for(int i=0;i<q;i++){
cin>>s>>k;
int x,p=d[s];
for(int j=0;j<k;j++){
cin>>x;
if(x<0){//向下跳
p-=x;
if(p>=d[son[s][18]])
p=d[son[s][18]];
s=down(s,p);
}
if(x>0){//向上跳
p-=x;
if(p<=1){
s=1;
p=1;
}
s=up(s,p);
}
}
cout<<down(s,p)<<endl;
}
return 0;
}

浙公网安备 33010602011771号