Description
You are given a tree (an acyclic undirected connected graph) with
N
nodes. The tree nodes are numbered from 1 to
We will ask you to perfrom some instructions of the following form:
0
i
: change the color of the
or
1
v
: ask for the id of the first black node on the path from node 1 to node
if it doesn’t exist, you may return -1 as its result.
Input
In the first line there are two integers
N
and
In the next
N−1
lines describe the edges in the tree: a line with two integers
a
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
题目解释
一棵结点为黑色或白色的树,初始都是白色的。有两种操作。
1. 将一个结点换颜色。
2. 询问从根到结点
思路
还是一道树链剖分水题,只是。。。只是线段树要多处理一下。每一段连续的区间存的是最小的黑色节点。如果没有黑色节点则赋值为
inf
。没了。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
const int maxn=100000;
const int inf=1000000000;
struct sigment_tree
{
int val[(maxn<<2)+10];
int updata(int now)
{
val[now]=std::min(val[now<<1],val[now<<1|1]);
return 0;
}
int build(int now,int left,int right)
{
if(left==right)
{
val[now]=inf;
return 0;
}
int mid=(left+right)>>1;
build(now<<1,left,mid);
build(now<<1|1,mid+1,right);
updata(now);
return 0;
}
int modify(int now,int left,int right,int findnum)
{
if((left>findnum)||(right<findnum))
{
return 0;
}
if(left==right)
{
if(val[now]==inf)
{
val[now]=left;
}
else
{
val[now]=inf;
}
return 0;
}
int mid=(left+right)>>1;
modify(now<<1,left,mid,findnum);
modify(now<<1|1,mid+1,right,findnum);
updata(now);
return 0;
}
int ask(int now,int left,int right,int askl,int askr)
{
if((askr<left)||(right<askl))
{
return inf;
}
if((askl<=left)&&(right<=askr))
{
return val[now];
}
int mid=(left+right)>>1;
return std::min(ask(now<<1,left,mid,askl,askr),ask(now<<1|1,mid+1,right,askl,askr));
}
};
int n;
struct tree
{
int pre[(maxn<<1)+10],now[maxn+10],son[(maxn<<1)+10],tot,cntpos[maxn+10];
int fa[maxn+10],wson[maxn+10],size[maxn+10],deep[maxn+10],top[maxn+10],dfn[maxn+10],cnt;
sigment_tree st;
int ins(int a,int b)
{
tot++;
pre[tot]=now[a];
now[a]=tot;
son[tot]=b;
return 0;
}
int first_dfs(int u,int father)
{
fa[u]=father;
size[u]=1;
deep[u]=deep[father]+1;
wson[u]=0;
int j=now[u];
while(j)
{
int v=son[j];
if(v!=father)
{
first_dfs(v,u);
size[u]+=size[v];
if((!wson[u])||(size[wson[u]]<size[v]))
{
wson[u]=v;
}
}
j=pre[j];
}
return 0;
}
int second_dfs(int u,int father,int topfather)
{
top[u]=topfather;
cnt++;
dfn[u]=cnt;
cntpos[cnt]=u;
if(wson[u])
{
second_dfs(wson[u],u,topfather);
}
int j=now[u];
while(j)
{
int v=son[j];
if((v!=father)&&(v!=wson[u]))
{
second_dfs(v,u,v);
}
j=pre[j];
}
return 0;
}
int change(int pos)
{
st.modify(1,1,n,dfn[pos]);
return 0;
}
int query(int x,int y)
{
int res=inf;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])
{
std::swap(x,y);
}
res=std::min(res,st.ask(1,1,n,dfn[top[x]],dfn[x]));
x=fa[top[x]];
}
if(deep[x]>deep[y])
{
std::swap(x,y);
}
res=std::min(res,st.ask(1,1,n,dfn[x],dfn[y]));
if(res==inf)
{
return -1;
}
return cntpos[res];
}
};
tree t;
int m;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<n; i++)
{
int a,b;
scanf("%d%d",&a,&b);
t.ins(a,b);
t.ins(b,a);
}
t.st.build(1,1,n);
t.first_dfs(1,0);
t.second_dfs(1,0,1);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
if(a)
{
printf("%d\n",t.query(1,b));
}
else
{
t.change(b);
}
}
return 0;
}