ZAIA_Enterprise @ 2023-05-25 22:14:24
#include <iostream>
using namespace std;
const int MAX_N = 100000;
long long arr[MAX_N + 1];
long long seg[4 * MAX_N];
long long lazy[4 * MAX_N];
void build(int p, int l, int r) {
if (l == r) {
seg[p] = arr[l];
return;
}
int mid = (l + r) / 2;
build(2 * p, l, mid);
build(2 * p + 1, mid + 1, r);
seg[p] = seg[2 * p] + seg[2 * p + 1];
}
void update(int nl, int nr, int p, int l, int r, long long k) {
if (lazy[p] != 0) {
seg[p] += lazy[p] * (r - l + 1);
if (l != r) {
lazy[2 * p] += lazy[p];
lazy[2 * p + 1] += lazy[p];
}
lazy[p] = 0;
}
if (nl <= l && r <= nr) {
seg[p] += k * (r - l + 1);
if (l != r) {
lazy[2 * p] += k;
lazy[2 * p + 1] += k;
}
return;
}
int mid = (l + r) / 2;
if (nl <= mid) update(nl, nr, 2 * p, l, mid, k);
if (nr > mid) update(nl, nr, 2 * p + 1, mid + 1, r, k);
seg[p] = seg[2 * p] + seg[2 * p + 1];
}
long long query(int ql, int qr, int p, int l, int r) {
if (lazy[p] != 0) {
seg[p] += lazy[p] * (r - l + 1);
if (l != r) {
lazy[2 * p] += lazy[p];
lazy[2 * p + 1] += lazy[p];
}
lazy[p] = 0;
}
if (ql <= l && r <= qr) {
return seg[p];
}
int mid = (l + r) / 2;
long long res = 0;
if (ql <= mid) res += query(ql, qr, 2 * p, l, mid);
if (qr > mid) res += query(ql, qr, 2 * p + 1, mid + 1, r);
return res;
}
int main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> arr[i];
}
build(1, 1, n);
while (m--) {
int op, x, y;
cin >> op >> x >> y;
if (op == 1) {
long long k;
cin >> k;
update(x, y, 1, 1, n, k);
} else {
cout << query(x, y, 1, 1, n) << endl;
}
}
return 0;
}
by xiaosuan @ 2023-05-26 09:30:07
@ ZAIA_Enterprise
在你的程序中,添加lazy
标记并不会直接更新seg
。
所以,在访问一个节点的seg
之前,必须要先将lazy
下传。
而这些代码在函数update
和函数query
中
在函数update
中,如果子区间与区间[ul, ur]
相交,就会调用子区间的update
函数从而下传lazy
。
但如果子区间与区间[ul, ur]
相离(也就是没有重合部分),子区间的update
函数将不会被调用,
也就不会去下传这个子区间的lazy
标记。
也就是说,在update
函数后面的
seg[p] = seg[2 * p] + seg[2 * p + 1];
操作中,子区间的seg
值是错误的。
by xiaosuan @ 2023-05-26 09:31:20
@ZAIA_Enterprise