在写完题目之后逛了一下讨论区,发现有很多同学反馈了数据过水的情况,例如 siz[u] += siz[v] 写成 siz[u] += v都能过,测试点有相同情况(这点我不清楚)等。
我刚学树剖,A 了这道题之后去写P7735 [NOI2021] 轻重边。因为突发奇想就把 dfs2 函数改了一种写法(当时没有深入想正确性):
正确写法是这样的:
void dfs2(int u, int t) {
//t为链顶
dfn[u] = ++tot;
top[u] = t;
a[tot] = val[u]; //线段树上是按照dfs序来操作的,因此要把点的编号转化为dfs序编号
if (son[u]) dfs2(son[u], t);
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if (v == fa[u]) continue;
if (v == son[u]) continue;
dfs2(v, v); //轻儿子要自己开一条重链
}
}
我改成了:
//换一种写法
void dfs2(int u, int t) {
//t为链顶
dfn[u] = ++tot;
top[u] = t;
a[tot] = val[u]; //线段树上是按照dfs序来操作的,因此要把点的编号转化为dfs序编号
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if (v == fa[u]) continue;
if (v == son[u]) dfs2(son[u], t); //备注:这里显然是错的!!!
else dfs2(v, v); //轻儿子要自己开一条重链
}
}
因为当时比较懒 qwq,所以就没有深入想正确性,直接交到这道题目上验证。
因为交上去之后同样 A了我就没怎么在意,直接用到 轻重边 那题去了。
因为这个错误,我 WA 20 pts,在调试过程中发现 dfs 部分 有问题,就发现了这个写法正确性有误。
树链剖分为了保证重链和子树的 dfs 序连续,要先遍历重儿子再遍历轻儿子,如果像我那样盲改就会出现一部分轻儿子被先遍历的情况。
改成正确的之后,轻重边那题就能过了,但是这题用错误的 dfs 函数仍然可以 AC,希望管理员能对此加强一下数据!
备注:刚学树剖,如果我代码还有别的错误请在评论区指出,谢谢!