传送门
解析:
树链剖分裸题啊。。。
我们每个重链开一个set按照深度维护一下黑点,每次查找只需要跳重链的同时看一下链上最浅的黑点在不在 v v v上面就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<20|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re char c;
while(!isdigit(c=gc()));re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
}
using namespace IO;
using std::cout;
cs int N=1e5+5;
int n,q;
std::vector<int> e[N];
inline void addedge(int u,int v){
e[u].push_back(v);
e[v].push_back(u);
}
int dep[N],fa[N],top[N],siz[N],son[N];
void dfs1(int u){
siz[u]=1;
for(int &v:e[u])
if(v^fa[u]){
fa[v]=u;
dep[v]=dep[u]+1;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u){
if(son[u]){
top[son[u]]=top[u];
dfs2(son[u]);
}
else return ;
for(int &v:e[u])
if(v!=fa[u]&&v!=son[u]){
top[v]=v;
dfs2(v);
}
}
struct cmp{bool operator()(cs int &u,cs int &v){return dep[u]<dep[v];}};
std::set<int,cmp> s[N];
bool col[N];
signed main(){
n=getint();q=getint();
for(int re i=1;i<n;++i)addedge(getint(),getint());
dfs1(1);top[1]=1;
dfs2(1);
while(q--){
switch(getint()){
case 0:{
int u=getint();
col[u]^=1;
if(col[u])s[top[u]].insert(u);
else s[top[u]].erase(u);
break;
}
case 1:{
int v=getint(),ans=-1;
while(top[v]!=1){
if(!s[top[v]].empty()&&dep[*s[top[v]].begin()]<=dep[v])ans=*s[top[v]].begin();
v=fa[top[v]];
}
if(!s[1].empty()&&dep[*s[1].begin()]<=dep[v])ans=*s[1].begin();
cout<<ans<<"\n";
break;
}
}
}
return 0;
}