题解 P5838 【USACO19DEC】Milk Visits G
RedreamMer · · 题解
前言
这道题似乎是我遇到的第一道用
不会(也没啥必要)
题意
给你一棵树,每个点有点权,每次询问节点
思路
以下
观察
如何记录这个点?
记录每个询问在
可以发现一个性质,若有一个点权为 (好像又是废话)。
并且,若这个权值为
因此:遍历到节点
发现这两条性质,就可以愉快做题了,因为
为了特判
注意特判询问
有时候看似很显然的性质,却有令人意想不到的思路。
时间复杂度
不管是码量还是效率,都远超大部分题解。
代码
#include <bits/stdc++.h>
using namespace std;
#define PB push_back
const int N = 1e5;
inline char nc()
{
static char buf[1000000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}
#define getchar nc
inline int read()
{
int s = 0;
register bool neg = 0;
register char c = getchar();
for (; c < '0' || c > '9'; c = getchar())
neg |= (c == '-');
for (; c >= '0' && c <= '9'; s = s * 10 + (c ^ 48), c = getchar())
;
s = (neg ? -s : s);
return s;
}
int a, b, s[N + 10], p[N + 10], ans[N + 10], top[N + 10];
vector<int> st[N + 10], ask[N + 10];
inline void dfs(int n, int fa)
{
int pp = top[s[n]];
for (int i = 0; i < ask[n].size(); i++)
{
int x = ask[n][i];
if (ans[x] == -1)
ans[x] = top[p[x]];
else
ans[x] = (top[p[x]] != ans[x]);
}
for (int i = 0; i < st[n].size(); i++)
{
int v = st[n][i];
if (v == fa)
continue;
top[s[n]] = v;
dfs(v, n);
}
top[s[n]] = pp;
}
signed main()
{
memset(ans, -1, sizeof(ans));
a = read();
b = read();
for (int i = 1; i <= a; i++)
s[i] = read();
int x, y, z;
for (int i = 1; i < a; i++)
{
x = read();
y = read();
st[x].PB(y);
st[y].PB(x);
}
for (int i = 1; i <= b; i++)
{
x = read();
y = read();
p[i] = read();
if (s[x] == p[i] || s[y] == p[i])
ans[i] = 1;
ask[x].PB(i);
ask[y].PB(i);
}
dfs(1, 0);
for (int i = 1; i <= b; i++)
printf("%d", ans[i]);
return 0;
}