Description
Analysis
首先,有一个显然却极其重要的性质:每个点的优先级是固定的。即,每次新来一个人必定去优先级最高的没人的点。
所以可以一遍dfs求出每个点的优先级。
考虑你要每次找出一个优先级最高的没人的点,同时还要支持让一个有人的房间重新变成没人的房间。你想到了什么?
没错,就是堆。
第二问显然可以倍增一下,整个过程用堆维护。
Code
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,b,a) for(int i=b;i>=a;i--)
#define efo(i,v) for(int i=0;i<a[v].size();i++)
using namespace std;
const int N=100010;
int n,tot,pd[N],b[N],c[N],heap[N*4],dep[N],f[N][20];
bool bz[N];
vector<int> a[N];
bool cmp(int x,int y)
{
return pd[x]<pd[y];
}
void dfs(int v,int fr,int d)
{
f[v][0]=fr,dep[v]=d;
efo(i,v)
{
int u=a[v][i];
if(u==fr) continue;
dfs(u,v,d+1);
}
pd[v]=++tot;
}
void add(int v)
{
heap[++tot]=v;
for(int son=tot;son>1 && b[heap[son]]<b[heap[son/2]];son/=2) swap(heap[son],heap[son/2]);
}
int get()
{
int t=heap[1];
heap[1]=heap[tot];
heap[tot--]=0;
for(int v=1;;)
{
int ls=v+v,rs=v+v+1,son;
if(!(b[heap[v]]>b[heap[ls]] && ls<=tot || b[heap[v]]>b[heap[rs]] && rs<=tot)) break;
if(rs>tot || b[heap[ls]]<b[heap[rs]])
son=ls;
else
son=rs;
swap(heap[v],heap[son]);
v=son;
}
return t;
}
int up(int v)
{
fd(i,log2(dep[v]),0)
if(bz[f[v][i]]) v=f[v][i];
return v;
}
int main()
{
int _,u,v,op,x,pos;
scanf("%d %d",&n,&_);
fo(i,1,n-1)
{
scanf("%d %d",&u,&v);
a[u].push_back(v);
a[v].push_back(u);
}
fo(i,1,n) c[i]=i,sort(a[i].begin(),a[i].end());
dfs(1,1,1);
fo(j,1,log2(n))
fo(i,1,n) f[i][j]=f[f[i][j-1]][j-1];
sort(c+1,c+n+1,cmp);
fo(i,1,n) b[c[i]]=i;
tot=0;
fo(i,1,n) add(i);
while(_--)
{
scanf("%d %d",&op,&x);
if(op==1)
{
fo(i,1,x)
bz[pos=get()]=1;
printf("%d\n",pos);
}
else
{
int y=up(x);
printf("%d\n",dep[x]-dep[y]);
add(y);bz[y]=0;
}
}
return 0;
}