我们可以将第一个黑点作为树的根。
令
fi
表示点
i
到根路径上点编号的最小值。那么因为根是黑点,每个点的答案一定包括
接下来考虑黑点
j
对
- 若
i
与
j 的 lca 是根,由于 fi 已经统计过了, j 对i 的贡献就是 fj - 若
i
与
j 的 lca 不是 j ,j 对 i 的贡献就是j 到 lca 路径上点编号的最小值与 i 到lca 路径上点编号的最小值。因为 lca 一定在 i 到根的路径上,贡献就是fj
那么黑点
j
对答案的贡献一定是
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define N 1000010
vector<int>g[N];
int i,j,k,n,m,p,a[N],q,x,y,Ans=1e9,Last;
inline int Min(int x,int y){
return x<y?x:y;
}
inline void Dfs(int x,int f){
a[x]=Min(a[f],x);
for(int i=0;i<g[x].size();i++)
if(g[x][i]!=f)Dfs(g[x][i],x);
}
int main(){
scanf("%d%d",&n,&q);q--;
memset(a,127,sizeof(a));
for(i=1;i<n;i++)scanf("%d%d",&x,&y),g[x].push_back(y),g[y].push_back(x);
scanf("%d%d",&x,&y);y=y%n+1;
Dfs(y,0);
while(q--){
scanf("%d%d",&x,&y);
y=(y+Last)%n+1;
if(x==1)Ans=Min(Ans,a[y]);else Last=Min(Ans,a[y]),printf("%d\n",Last);
}
return 0;
}