<<P4116 Qtree3>>
题目描述
给出 N 个点的一棵树(N−1 条边),节点有白有黑,初始全为白。
有两种操作:
0 i
:改变某点的颜色(原来是黑的变白,原来是白的变黑)。
1 v
:询问 1 到 v 的路径上的第一个黑点,若无,输出 −1。
输入格式
第一行 N,Q,表示 N 个点和 Q 个操作。
第二行到第 N 行 N−1 条无向边。
再之后 Q 行,每行一个操作 0 i
或者 1 v
。
输出格式
对每个 1 v
操作输出结果
输入输出样例
输入 #1复制
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
输出 #1复制
-1 8 -1 2 -1
说明/提示
对于 1/3 的数据有 N=5000,Q=400000。
对于 1/3 的数据有 N=10000,Q=300000。
对于 1/3 的数据有 N=100000,Q=100000。
此外,有1≤i,v≤N。
代码实现:
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<set>
using namespace std;
#define INF 1000000000
#define pprint(x) print(x),putchar(' ')
#define fprint(x) print(x),putchar('\n')
char BB[1 << 15],*SS = BB,*TT = BB;
inline long long read()
{
long long val = 0;int sign = 1;
char ch = getchar();
for(;!isdigit(ch);ch = getchar())
if(ch == '-')
sign = -1;
for(;isdigit(ch);ch = getchar())
val = val * 10 + (ch ^ 48);
return val * sign;
}
void print(long long num)
{
if(num < 0)
putchar('-'),num = -num;
if(num > 9)
print(num / 10);
putchar(num % 10 + '0');
}
const int N = 100010;
int depth[N];
struct TreePartition
{
struct Edge
{
int next,to;
}edges[N << 1];
int head[N],edgeCount;
void add(int from,int to)
{
edges[++edgeCount].to = to,edges[edgeCount].next = head[from];
head[from] = edgeCount;
}
void addEdge(int from,int to)
{
add(from,to),add(to,from);
}
int color[N],father[N],size[N],heavySon[N],chainTop[N];
struct Compare{bool operator()(const int &a,const int &b){ return depth[a] < depth[b]; }};
set<int,Compare> nodes[N];
void dfs1(int node,int parent)
{
father[node] = parent,depth[node] = depth[parent] + 1,size[node] = 1;
heavySon[node] = 0;
for(int i = head[node];i;i = edges[i].next)
{
int neighbor = edges[i].to;
if(neighbor == parent)
continue;
dfs1(neighbor,node);
size[node] += size[neighbor];
if(size[neighbor] > size[heavySon[node]])
heavySon[node] = neighbor;
}
}
void dfs2(int node,int top)
{
chainTop[node] = top;
if(!heavySon[node])
return;
dfs2(heavySon[node],top);
for(int i = head[node];i;i = edges[i].next)
{
int neighbor = edges[i].to;
if(neighbor == father[node] || neighbor == heavySon[node])
continue;
dfs2(neighbor,neighbor);
}
}
void toggle(int node)
{
if(color[node] ^= 1)
nodes[chainTop[node]].insert(node);
else
nodes[chainTop[node]].erase(node);
}
int query(int node)
{
int result = -1;
while(node)
{
int candidate = *nodes[chainTop[node]].begin();
if(nodes[chainTop[node]].size())
if(depth[candidate] <= depth[node])
result = candidate;
node = father[chainTop[node]];
}
return result;
}
void initialize()
{
dfs1(1,0);
dfs2(1,1);
}
}tree;
int main()
{
int nodeCount = read(),queryCount = read();
for(int i = 1;i < nodeCount;i++)
tree.addEdge(read(),read());
tree.initialize();
while(queryCount--)
{
int operation = read();
if(!operation)
tree.toggle(read());
else
fprint(tree.query(read()));
}
return 0;
}