背景:
同今天的上一篇。
题目传送门:
https://www.luogu.org/problemnew/show/P4116
题意:
一棵树,每一个点有两种颜色,现在支持更换点的颜色和查询
1
1
1到
x
x
x路径上某种颜色的出现的第一次位置。
思路:
用树剖即可。
改颜色照常该。
询问位置只需在线段树中再次查询即可(注意要取
d
e
e
p
deep
deep更小的)。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,q,u=0,len=0;
struct node1{int x,y,next;} a[200010];
struct node2{int d,l,r,lc,rc;} tr[200010];
int last[200010],p[200010],tot[200010],son[200010],fa[200010],dep[200010],ys[200010],yss[200010],top[200010],ans[200010];
void ins(int x,int y)
{
a[++len]=(node1){x,y,last[x]}; last[x]=len;
}
void build(int l,int r)
{
int now=++len;
tr[now]=(node2){0,l,r,-1,-1};
if(l<r)
{
int mid=(l+r)>>1;
tr[now].lc=len+1; build(l,mid);
tr[now].rc=len+1; build(mid+1,r);
}
}
void change(int now,int x)
{
if(tr[now].l==tr[now].r)
{
tr[now].d^=1;
return;
}
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)>>1;
if(x<=mid) change(lc,x); else change(rc,x);
tr[now].d=tr[lc].d+tr[rc].d;
}
int findsum(int now,int l,int r)
{
if(tr[now].l==l&&tr[now].r==r) return tr[now].d;
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)>>1;
if(r<=mid) return findsum(lc,l,r);
else if(mid+1<=l) return findsum(rc,l,r);
else return findsum(lc,l,mid)+findsum(rc,mid+1,r);
}
int find(int now,int l,int r)
{
if(l==r) return yss[l];
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)>>1;
if(r<=mid) return find(lc,l,r);
else if(mid+1<=l) return find(rc,l,r);
else return findsum(lc,l,mid)?find(lc,l,mid):find(rc,mid+1,r);
}
void dfs1(int x)
{
tot[x]=1;
son[x]=0;
for(int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(y==fa[x]) continue;
fa[y]=x;
dep[y]=dep[x]+1;
dfs1(y);
if(tot[son[x]]<tot[y]) son[x]=y;
tot[x]+=tot[y];
}
}
void dfs2(int x,int tp)
{
ys[x]=++u;
yss[u]=x;
top[x]=tp;
if(son[x]) dfs2(son[x],tp);
for(int i=last[x];i;i=a[i].next)
{
int y=a[i].y;
if(y!=son[x]&&y!=fa[x]) dfs2(y,y);
}
}
int solve(int x,int y)
{
int tx=top[x],ty=top[y],t1=0,t2=0;
while(tx!=ty)
{
if(dep[tx]>dep[ty]) swap(x,y),swap(tx,ty);
if(findsum(1,ys[ty],ys[y])) t1=ys[ty],t2=ys[y];
y=fa[ty];ty=top[y];
}
if(dep[x]>dep[y]) swap(x,y);
if(findsum(1,ys[x],ys[y])) t1=ys[x],t2=ys[y];
if(t1&&t2) return find(1,t1,t2); else return -1;
}
int main()
{
int t,x,y;
scanf("%d %d",&n,&m);
for(int i=1;i<n;i++)
{
scanf("%d %d",&x,&y);
ins(x,y),ins(y,x);
}
len=0;
build(1,n);
fa[1]=0;
dep[1]=1;
dfs1(1);
dfs2(1,0);
for(int i=1;i<=m;i++)
{
scanf("%d %d",&t,&x);
if(!t) change(1,ys[x]); else printf("%d\n",solve(1,x));
}
}