专栏文章
线段树小记
算法·理论参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minnpyy1
- 此快照首次捕获于
- 2025/12/02 05:24 3 个月前
- 此快照最后确认于
- 2025/12/02 05:24 3 个月前
如题
线段树是一个二叉搜索树,可以将 的扫变成 ,适用范围很广,可以在线维护修改以及查询区间上的最值,求和。
习惯写
pushup:求区间和的
CPPvoid pushup(int t) {
sum[t] = sum[t << 1] + sum[t << 1 | 1];
}
然后是
CPPpushnow:void pushnow(int t, int l, int r, int v) {
sum[t] += (r - l + 1) * v;
tag[t] += v;
}
tag 是懒标记,先把 sum 加上该加的,就是子树的和,然后打上懒标记,方便之后往下传。最后是
CPPpushdown,即往下传懒标记:void pushdown(int t, int l, int r) {
if (!tag[t]) return; // 如果没有懒标记就返回
int mid = (l + r) >> 1;
pushnow(t << 1, l, mid, tag[t]);
pushnow(t << 1 | 1, mid + 1, r, tag[t]);
tag[t] = 0; // 往子树传完后把自己的懒标记删掉
}
建树:
CPPvoid build(int t, int l, int r) {
if (l == r) {
sum[t] = a[l];
return;
}
int mid = (l + r) >> 1;
build(t << 1, l, mid);
build(t << 1 | 1, mid + 1, r);
pushup(t);
}
区间修改:
CPPvoid modify(int t, int l, int r, int ql, int qr, int v) {
if (ql <= l && r <= qr) {
pushnow(t, l, r, v);
return;
}
pushdown(t, l, r);
int mid = (l + r) >> 1;
if (ql <= mid) modify(t << 1, l, mid, ql, qr, v);
if (qr > mid) modify(t << 1 | 1, mid + 1, r, ql, qr, v);
pushup(t);
}
区间查询:
CPPint query(int t, int l, int r, int ql, int qr) {
if (ql <= l && r <= qr) return sum[t];
pushdown(t, l, r);
int mid = (l + r) >> 1, res = 0;
if (ql <= mid) res += query(t << 1, l, mid, ql, qr);
if (qr > mid) res += query(t << 1 | 1, mid + 1, r, ql, qr);
pushup(t);
return res;
}
然后就可以解决线段树 1 这道题。
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...