最近在讲课的时候,竟然连续WA了一道线段树的题,一番debug下来才意识到自己犯了和很久之前一样的错误。
个人习惯:打上lazy标记表示此区间内(包含此节点)的数据未更新。
修改时:直接返回要下放,查询子区间要下放,pushup前要将子区间的标记也下放。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| void update(int x, int l, int r, int ql, int qr, const Mat &k) { if (ql <= l && r <= qr) { laz[x] *= k; down(x); return; } down(x); gm; if (ql <= mid) update(ls, l, mid, ql, qr, k); else down(ls); if (mid < qr) update(rs, mid + 1, r, ql, qr, k); else down(rs); up(x); }
|
注意,对于标记互相冲突(有先后顺序的标记),应该在进入节点时先pushdown一遍。
另外,在pushup时,一定要判断rs是否超过了线段树数组M的范围,不然就要开8倍的空间。这是因为有时候会pushdown叶子节点。
1 2 3 4 5 6 7 8 9 10
| il void down(int x, int len) { if(laz[x]) { sum[x] += laz[x] * len; if(rs < M) { laz[ls] += laz[x], laz[rs] += laz[x]; } laz[x] = 0; } }
|