Description
Solution
先一问一问来,
对于第一问,先给每个点一个优先值,很显然每个点的优先值都是一定的,每次一定选优先值最大的点,然后删掉。这个可以用堆(C++有优先队列)来实现,
对于第二问,很显然删除当前点后,移动的点一定是连续的,所以直接用LCA跳即可,
复杂度: O(nlog(n))
Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
#define iff() if(B[i][1]!=fa)
using namespace std;
const int N=100500;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,ans;
bool Z[N];
int G[N][21],C[N],No[N];
int B[2*N][2],A[N],B0;
struct wq{int q,w;}SC[N*2];
struct qqww
{
int n;
friend bool operator <(qqww q,qqww w){return No[q.n]>No[w.n];}
}cty;
priority_queue<qqww>d;
bool PX(wq q,wq w){return q.q>w.q||(q.q==w.q&&q.w>w.w);}
void link(int q,int w){B[++B0][0]=A[q];A[q]=B0,B[B0][1]=w;}
void dfs(int q,int fa,int c)
{
G[q][0]=fa,C[q]=c;
efo(i,q)
iff()dfs(B[i][1],q,c+1);
No[q]=++No[0];
}
int find(int q)
{
while(Z[G[q][0]])
{
int I=0;
while(Z[G[G[q][I+1]][0]])I++;
q=G[q][I];
}
return q;
}
int main()
{
int q,w,_;
read(n),read(_);
fo(i,1,n-1)SC[i+n-1].w=read(SC[i].q),SC[i+n-1].q=read(SC[i].w);
sort(SC+1,SC+2*n-1,PX);
fo(i,1,2*n-2)link(SC[i].q,SC[i].w);
dfs(1,0,1);
fo(j,1,20)fo(i,1,n)G[i][j]=G[G[i][j-1]][j-1];
fo(i,1,n)cty.n=i,d.push(cty);
while(_--)
{
read(w),read(q);
if(w-1)
{
w=find(q);
printf("%d\n",C[q]-C[w]);
Z[w]=0;cty.n=w;
d.push(cty);
}
else
{
w=q;
while(w--)
{
cty=d.top();
Z[cty.n]=1;
d.pop();
}
printf("%d\n",cty.n);
}
}
return 0;
}