有关线段树合并的写法
查看原帖
有关线段树合并的写法
1051647
fight_for_humanity楼主2024/11/20 21:41

对于第一篇题解而言,我的写法有所差异,而调了好一会。

题解中的 dfs 中,写有 rt[u] = seg.Newnode(); 的原因:

代码中 pushdown 如果没有 lslsrsrs 会改动 tr[0]tr[0] 的信息, 为了不受影响,先前使得 rt[u]rt[u] 不为 00

我的写法,在 dfs 中不写 rt[u] = seg.Newnode();,在 modify 中判断 pp00 时给它新开标号的时候:

为了避免出现当前 rt[u]rt[u]00 但会受到 pushdown 的影响, 我们在 pushdown 时加上判断,如果没有 lslsrsrs,就赋一个新的节点给他们。 如下:

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==minmax == min 时删去所有儿子。 如果先判断相同再 pushdown,在 max==minmax == min 的情况下,pushdown 是会把生成的新的儿子改为标记的模样。

所以我们对于做类似势能线段树的区间取 maxmax 操作加上线段树合并时:

  1. 注意 tr[0]tr[0] 节点的值是否有所修改;
  2. 注意因为 max==minmax == min 的删除操作所带来的的影响,恢复时要保证正确状态。

我也挂一下我的写法

2024/11/20 21:41
加载中...