By zhongzijun \text{zhongzijun} zhongzijun
Description
1 ≤ n , t ≤ 1 0 5 1 \leq n,t \leq10^5 1≤n,t≤105
Solution
我们可以先用深搜求出每一个点的 优先级 和 深度 。
优先级指的是来的人进入树的节点的顺序,值越小表示越早进入。
然后用一个堆来维护这个优先级。
这样子每次做 1 1 1 操作的时候就可以直接在堆里取了。
然后我们用一个数组 b j [ ] bj[] bj[] 来表示一个点是否有人。
当 b j [ i ] = 1 bj[i]=1 bj[i]=1 是表示 i i i 号点有人,为 0 0 0 表示 i i i 号点没有人。
对于 2 2 2 操作,我们发现对于一个点 p p p ,我们取完点 p p p 移动完后的状态相当于拿掉从点 p p p 到根节点的路径上有人的点中深度最小的那个点然后不移动。
我们不放设 从点 p p p 到根节点的路径上有人的点中深度最小的那个点 为点 q q q 。
如果我们设点 i i i 的深度为 d e p i dep_i depi ,那么这次 2 2 2 操作的答案就是 ( d e p p − d e p q ) (dep_p-dep_q) (depp−depq) 。求点 q q q 是可以用倍增来做的。
注意在做完 2 2 2 操作后把点 p p p 放回堆中并且维护堆。
然后这道题就做完了。
时间复杂度 O ( ( n + t )    log    n ) O((n+t)\;\log\;n) O((n+t)logn) 。
Code
#include <cstdio>
struct node{ int x,y,g; } b[1000001];
int color[1000001],vis[1000001],dep[1000001],bj[1000001];
int h[1000001],d[1000001],u[1000001],f[500001][21];
int len=0,p=0,n=0,T=0;
inline int read()
{
char c;
while((c=getchar())>'9' || c<'0');
int ans=c-'0';
while((c=getchar())>='0' && c<='9')
{
ans=(ans<<3)+(ans<<1)+(c-'0');
}
return ans;
}
inline int min(int x,int y)
{
return x<y?x:y;
}
inline void ins(int x,int y)
{
len++;
b[len].x=x;
b[len].y=y;
b[len].g=h[x];
h[x]=len;
}
inline void dfs(int x)
{
int dq=0;
bool flag=false;
vis[x]=1;
while(true)
{
dq=n+1;
for(int i=h[x];i>0;i=b[i].g)
{
if(color[b[i].y]==0 && vis[b[i].y]==0)
{
dq=min(dq,b[i].y);
}
}
if(dq==n+1)
{
break;
}
vis[dq]=1;
dfs(dq);
d[++p]=dq;
color[dq]=1;
}
}
inline void dfs2(int x)
{
for(int i=h[x];i>0;i=b[i].g)
{
int y=b[i].y;
if(dep[y]==0)
{
dep[y]=dep[x]+1;
f[y][0]=x;
dfs2(y);
}
}
}
inline void pushdown(int x)
{
int lson=x*2,rson=x*2+1;
if(x*2>n)
{
return ;
}
if(x*2+1>n)
{
if(u[d[x]]>u[d[lson]])
{
int t=d[x];
d[x]=d[lson];
d[lson]=t;
pushdown(lson);
}
return ;
}
if(u[d[x]]>u[d[lson]] && u[d[x]]>u[d[rson]])
{
if(u[d[lson]]<u[d[rson]])
{
int t=d[x];
d[x]=d[lson];
d[lson]=t;
pushdown(lson);
}
else
{
int t=d[x];
d[x]=d[rson];
d[rson]=t;
pushdown(rson);
}
}
else if(u[d[x]]>u[d[lson]])
{
int t=d[x];
d[x]=d[lson];
d[lson]=t;
pushdown(lson);
}
else if(u[d[x]]>u[d[rson]])
{
int t=d[x];
d[x]=d[rson];
d[rson]=t;
pushdown(rson);
}
}
inline void pushup(int x)
{
if(x==1)
{
return ;
}
int fa=x/2;
if(u[d[x]]<u[d[fa]])
{
int t=d[x];
d[x]=d[fa];
d[fa]=t;
pushup(fa);
}
}
int main()
{
scanf("%d %d",&n,&T);
for(int i=1;i<=n-1;i++)
{
int x=0,y=0;
x=read(),y=read();
ins(x,y),ins(y,x);
}
dfs(1);
dep[1]=1;
dfs2(1);
for(int j=1;j<=20;j++)
{
for(int i=1;i<=n;i++)
{
f[i][j]=f[f[i][j-1]][j-1];
}
}
d[n]=1;
for(int i=1;i<=n;i++)
{
u[d[i]]=i;
}
u[0]=999999999;
while(T--)
{
int t=0,x=0;
t=read(),x=read();
if(t==1)
{
int dqans=0;
for(int i=1;i<=x;i++)
{
dqans=d[1];
bj[d[1]]=1;
d[1]=d[n];
d[n]=0;
n--;
pushdown(1);
}
printf("%d\n",dqans);
}
else if(t==2)
{
int tx=x;
for(int i=20;i>=0;i--)
{
if(f[tx][i]!=0 && bj[f[tx][i]]==1)
{
tx=f[tx][i];
}
}
bj[tx]=0;
d[++n]=tx;
pushup(n);
printf("%d\n",dep[x]-dep[tx]);
}
}
return 0;
}