现在有 \(n\) 次操作,每次将一个点设为黑色,或者查询:从当前点到任意黑点路径上最小值的最小值。保证第一次操作是设置黑点。强制在线。

我们考虑这样一个过程,我们把第一次操作的点设为根,从根出发进行 dfs,找到每个点到根的最小值 \(a_x\)。这样如果不增加新的黑点,查询 \(x\) 点的答案就是 \(a_x\)

然后考虑加入了新黑点 \(y\),询问 \(x\),我们发现答案就是 \(\min(a_y,a_x)\),因为 \(a_y\) 造成的贡献可以分成两部分 \(y\rightarrow lca(x,y)\)\(lca(x,y)\rightarrow root\)。其中第一部分是从 \(x\)\(y\) 可以经过的,第二部分是 \(x\)\(root\) 可以经过的。

而路径上的点又分成 \(y\rightarrow lca(x,y)\)\(x\rightarrow lca(x,y)\),分别被 \(a_y\)\(a_x\) 包括了。也就做到了不重不漏。

那么,假设当前的黑点点集是 \(S\),答案就是 \(\min(\min_{i\in S}a_i,a_x)\)

动态记录所有黑点的最小值即可。

int n,a[1000005],q,t,x,ans=0,res,a,b;
vt<int>vv[1000005];
inline void dfs(int x,int p){
	a[x]=min(x,a[p]);
	for(auto j:vv[x])if(j!=p){
		dfs(j,x);
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);a[0]=1e9;
	cin>>n>>q;
	rp(i,n-1){
		cin>>a>>b;
		vv[a].pb(b);
		vv[b].pb(a);
	}
	cin>>t>>x;x=(x+0)%n+1;
	dfs(x,0);
	res=x;
	rd(_,q-1){
		cin>>t>>x;
		x=(x+ans)%n+1;
		if(t==1)res=min(res,a[x]);
		else {
			ans=min(res,a[x]);
			cout<<ans<<'\n';
		}
	}
	return 0;
}
//Crayan_r