【题意】
一棵树有n个节点,初始均为白色,有两种操作:
1. 1 x 代表把结点 x 设置为黑色
2. 2 x 代表查询 x 到树上任意一个黑色结点的简单路径上的编号最小的结点的编号
输入 t 和 z ,其中 t 表示操作类型, x=(last+z)mod n+1,last代表上一次询问答案,初始为 0 ,保证第一个操作为 1
【数据范围】
n,q<=1e6.
【题解】
发现第一个操作保证是1,则可以以第一个染黑的点为根,则每个点到它路径上最小值dis[i]可以预处理出。
发现一个点到所有黑点路径中编号最小的为每个黑点与这个点到根上的编号最小值。
代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int n,q,last[N],dis[N],size,last1,opt,xx,zx;
struct pigu
{
int dao,ne;
}a[N<<1];
inline void lingjiebiao(int x,int y)
{
a[++size].dao=y;
a[size].ne=last[x];
last[x]=size;
}
inline void dfs(int now,int fa)
{
dis[now]=min(dis[now],now);
for(int i=last[now];i;i=a[i].ne)
{
if(a[i].dao==fa) continue;
dis[a[i].dao]=dis[now];
dfs(a[i].dao,now);
}
}
inline int read()
{
char c=getchar();
int x=0;
while(!isdigit(c)) c=getchar();
while(isdigit(c)) {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return x;
}
int main()
{
memset(dis,0x3f,sizeof(dis));
n=read();q=read();
for(int i=1,x,y;i<=n-1;i++)
{
x=read();y=read();
lingjiebiao(x,y);
lingjiebiao(y,x);
}
opt=read();xx=read();
int rt=xx%n+1;
dfs(rt,0);
zx=dis[rt];
for(int i=1;i<=q-1;i++)
{
opt=read();xx=read();
xx=(last1+xx)%n+1;
if(opt==1)
{
zx=min(zx,dis[xx]);
}
else
{
cout<<min(zx,dis[xx])<<"
";
xx=min(zx,dis[xx]);
last1=xx;
}
}
}