对于第一篇题解而言,我的写法有所差异,而调了好一会。
题解中的 dfs 中,写有 rt[u] = seg.Newnode();
的原因:
代码中 pushdown
如果没有 ls 或 rs 会改动 tr[0] 的信息,
为了不受影响,先前使得 rt[u] 不为 0。
我的写法,在 dfs 中不写 rt[u] = seg.Newnode();
,在 modify
中判断 p 为 0 时给它新开标号的时候:
为了避免出现当前 rt[u] 是 0 但会受到 pushdown
的影响,
我们在 pushdown
时加上判断,如果没有 ls 或 rs,就赋一个新的节点给他们。
如下:
inline void pushdown(int p){
if(!tr[p].tag)return ;
if(!tr[p].ls)tr[p].ls = Newnode();
if(!tr[p].rs)tr[p].rs = Newnode();
Plus(tr[p].ls, tr[p].tag);
Plus(tr[p].rs, tr[p].tag);
tr[p].tag = 0;
}
还有一点:
pushdown
要在判断区间相同之前。
原因:
我们的 pushup
操作中有区间 max==min 时删去所有儿子。
如果先判断相同再 pushdown
,在 max==min 的情况下,pushdown
是会把生成的新的儿子改为标记的模样。
所以我们对于做类似势能线段树的区间取 max 操作加上线段树合并时:
- 注意 tr[0] 节点的值是否有所修改;
- 注意因为 max==min 的删除操作所带来的的影响,恢复时要保证正确状态。
我也挂一下我的写法。