RevolutionBP @ 2022-02-24 21:05:38
/*
BlackPink is the Revolution
light up the sky
Blackpink in your area
*/
#include <algorithm>
#include <bitset>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
#define rep(i, a, b) for (int i = (a); (i) <= (b); ++i)
#define per(i, a, b) for (int i = (a); (i) >= (b); --i)
#define whlie while
using namespace std;
const int N = 1e7 + 5;
const int K = 1e7 + 5;
typedef long long ll;
typedef pair<int, int> P;
namespace scan {
template <typename T>
inline void read(T& x) {
x = 0;
char c = getchar();
int f = 0;
for (; !isdigit(c); c = getchar())
f |= (c == '-');
for (; isdigit(c); c = getchar())
x = x * 10 + (c ^ 48);
if (f)
x = -x;
}
template <typename T, typename... Args>
inline void read(T& x, Args&... args) {
read(x), read(args...);
}
template <typename T>
inline void write(T x, char ch) {
if (x < 0)
putchar('-'), x = -x;
static short st[30], tp;
do
st[++tp] = x % 10, x /= 10;
while (x);
while (tp)
putchar(st[tp--] | 48);
putchar(ch);
}
template <typename T>
inline void write(T x) {
if (x < 0)
putchar('-'), x = -x;
static short st[30], tp;
do
st[++tp] = x % 10, x /= 10;
while (x);
while (tp)
putchar(st[tp--] | 48);
}
inline void write(char ch) {
putchar(ch);
}
} // namespace scan
using namespace scan;
int n, m, cnt, T, sum, sumsiz, rt;
int maxsiz[N], siz[N], head[N], dis[N], ans[N], q[N];
bool vis[N], exist[N];
vector<int> tmp;
queue<int> tag;
struct edge {
int to, val, nxt;
} e[N << 1];
inline void add(int u, int v, int w) {
e[++cnt] = (edge){v, w, head[u]};
head[u] = cnt;
}
inline void CalcSize(int u, int f) {
siz[u] = 1;
maxsiz[u] = 0;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v == f || vis[v])
continue;
CalcSize(v, u);
maxsiz[u] = max(maxsiz[u], siz[v]);
siz[u] += siz[v];
}
maxsiz[u] = max(maxsiz[u], sumsiz - siz[u]);
if (maxsiz[u] < maxsiz[rt])
rt = u;
}
void Calc(int u, int f) {
tmp.push_back(dis[u]);
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to, w = e[i].val;
if (v == f || vis[v])
continue;
dis[v] = dis[u] + w;
Calc(v, u);
}
}
inline void Calc2(int u, int f) {
exist[0] = true;
tag.push(0);
vis[u] = true;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to, w = e[i].val;
if (v == f || vis[v])
continue;
dis[v] = w;
Calc(v, u);
int sizz = tmp.size() - 1;
rep(j, 0, sizz)
rep(k, 1, m)
if (q[k] >= tmp[j])
ans[k] |= exist[q[k] - tmp[j]];
rep(j, 0, sizz) {
if (tmp[j] < K) {
tag.push(tmp[j]);
exist[tmp[j]] = true;
}
}
tmp.clear();
}
while (!tag.empty())
exist[tag.front()] = false, tag.pop();
}
inline void dfs(int u, int f) {
Calc2(u, f);
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v == f || vis[v])
continue;
sumsiz = siz[v];
rt = 0;
maxsiz[rt] = N;
CalcSize(v, u), Calc(rt, 0), dfs(rt, 0);
}
}
int main() {
read(n, m);
rep(i, 1, n - 1) {
int u, v, w;
read(u, v, w);
add(u, v, w);
add(v, u, w);
}
rep(i, 1, m) read(q[i]);
maxsiz[rt] = N;
sumsiz = n;
CalcSize(1, 0);
Calc(rt, 0);
dfs(rt, 0);
rep(i, 1, m) puts(ans[i] ? "AYE" : "NAY");
return 0;
}
// write:RevolutionBP
by RevolutionBP @ 2022-02-24 21:07:02
说错了,是4和6wa了
代码得分
by LawrenceSivan @ 2022-02-27 20:56:01
@RevolutionBP
我看明白是哪里的问题了。
情况是这样的。
CalcSize(1, 0);
Calc(rt, 0);
dfs(rt, 0);
你每次进行分治的时候,都会首先寻找重心,这个是正确的,但是你之后紧接着进行了一次 Calc
操作,这个操作其实是不必要的,你在 dfs
的过程中就会自然的处理,并不需要你进行这一次 calc
,相反的,由于你进行了这一次 calc
操作,导致你的 tmp
数组每次开始时并不是清零的状态,而是充满了这个点为根的子树的距离值,这也就导致你后面的分治出现了问题
by LawrenceSivan @ 2022-02-27 20:57:12
@RevolutionBP 更改后的提交记录
by LawrenceSivan @ 2022-02-27 20:57:49
@RevolutionBP 为了帮助你理解,我绘制了一些图片,你可以抽空看一下
by LawrenceSivan @ 2022-02-27 21:04:04
@RevolutionBP
by LawrenceSivan @ 2022-02-27 21:06:24
@RevolutionBP 并且对于你的 calc2
函数内,为了防止自己子树内拼接导致路径重复问题,我们要先尝试拼接,再把自己子树内的值加入
by LawrenceSivan @ 2022-02-27 21:09:11
@RevolutionBP
也就是为了避免这种情况
by LawrenceSivan @ 2022-02-27 21:09:48
@RevolutionBP 说的可能啰嗦了点,希望你能看懂。加油!