一棵结点为黑色或白色的树,初始都是白色的。有两种操作
1 将一个结点换颜色
2 询问从根到结点u路径上面的第一个黑色点,没有则输出-1
Input
In the first line there are two integers N and Q.
In the next N-1 lines describe the edges in the tree: a line with two integers a b denotes an edge
between a and b. The next Q lines contain instructions "0 i" or "1 v" (1 ≤ i, v ≤ N).
Output
For each "1 v" operation, write one integer representing its result.
Sample Input
9 8
1 2
1 3
2 4
2 9
5 9
7 9
8 9
6 8
1 3
0 8
1 6
1 7
0 2
1 9
0 2
1 9
Sample Output
-1
8
-1
2
-1
#include<cstdio> #include<algorithm> #include<cstring> using namespace std;const int N=200001; int n,m,sum,cnt,now,pre[N],f[N],nxt[N],h[N],top[N],id[N],size[N],dep[N],ans,maxx,di[N]; struct oo{int a,b,dp,now;bool v;}s[N*2-20000]; void dfs(int x) { size[x]=1; for(int i=h[x];i;i=nxt[i]) { if(pre[i]==f[x])continue; dep[pre[i]]=dep[x]+1; f[pre[i]]=x; dfs(pre[i]); size[x]+=size[pre[i]]; } } void dfs2(int x,int f) { int k=0; id[x]=++cnt; di[cnt]=x; //dfs序中第cnt个点是x top[x]=f; for(int i=h[x];i;i=nxt[i]) if(size[pre[i]]>size[k]&&dep[pre[i]]>dep[x])k=pre[i]; if(!k)return ; dfs2(k,f); for(int i=h[x];i;i=nxt[i]) if(dep[pre[i]]>dep[x]&&pre[i]!=k) dfs2(pre[i],pre[i]); } void ins(int x,int y) { pre[++now]=y; nxt[now]=h[x]; h[x]=now; } void build(int x,int l,int r) { s[x].a=l,s[x].b=r; s[x].dp=1e9; if(l==r) { return ; } build(x<<1,l,l+r>>1); build(x<<1|1,(l+r>>1)+1,r); } void get(int x,int l,int r) //求出线段树上[l,r]哪个点是黑色的,且深度最小 { if(s[x].a>=l&&r>=s[x].b) { if(s[x].dp<maxx) { maxx=s[x].dp; //找出深度最小值 sum=s[x].now;//对应的点 } return ; } else { int mid=s[x].a+s[x].b>>1; if(l<=mid)get(x<<1,l,r); if(r>mid)get(x<<1|1,l,r); } } void qmax(int x,int y) { maxx=1e9,sum=-1; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); get(1,id[top[x]],id[x]); x=f[top[x]]; } if(id[x]>id[y]) swap(x,y); get(1,id[x],id[y]); if(sum==0) sum=-1; } void change(int x,int l) //x指目前在哪个树上 //l是指线段中哪个位置 { if(s[x].a==s[x].b) { s[x].v^=1; if(s[x].v) //如果染成黑色 { s[x].dp=dep[di[l]]; //求出深度 s[x].now=di[l]; //di[l]指dfs序列中第l个点是原树上哪个点 } else //还原成白色 s[x].dp=1e9,s[x].now=0; return ; } int mid=s[x].a+s[x].b>>1; if(l<=mid) change(x<<1,l); else change(x<<1|1,l); if(s[x<<1].dp<s[x<<1|1].dp)//求出最小的深度 { s[x].dp=s[x<<1].dp; s[x].now=s[x<<1].now; } else { s[x].dp=s[x<<1|1].dp; s[x].now=s[x<<1|1].now; } } int main() { scanf("%d%d",&n,&m); for(int i=1,x,y;i<n;i++) { scanf("%d%d",&x,&y); ins(x,y); ins(y,x); } dfs(1); dfs2(1,1); build(1,1,n); int c; for(int i=1;i<=m;i++) { int a,b; scanf("%d",&c); if(c) //查询操作 { scanf("%d",&b); qmax(1,b); printf("%d ",sum); } if(!c) //将某个结点换颜色 scanf("%d",&b),change(1,id[b]); } }