#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5;
int n, q;
int a[N + 5], tree[(N + 5) * 4], lzytag[(N + 5) * 4];
int ls(int x) { return x << 1;}
int rs(int x) { return x << 1 | 1;}
void pushup(int x) {
tree[x] = tree[ls(x)] + tree[rs(x)];
}
void build(int x, int xl, int xr) {
lzytag[x] = 0;
if(xl == xr) { tree[x] = tree[xl]; return;}
int mid = (xl + xr) / 2;
build(ls(x), xl, mid); build(rs(x), mid + 1, xr);
}
void addtag(int x, int xl, int xr, int val) {
lzytag[x] += val;
tree[x] += val * (xr - xl + 1);
}
void pushdown(int x, int xl, int xr) {
if(lzytag[x] != 0) {
int mid = (xl + xr) / 2;
addtag(ls(x), xl, mid, lzytag[x]); addtag(rs(x), mid + 1, xr, lzytag[x]);
lzytag[x] = 0;
}
}
void update(int l, int r, int x, int xl, int xr, int val) {
if (l <= xl && xr <= r) {
addtag(x, xl, xr, val);
return ;
}
pushdown(x, xl, xr);
int mid = (xl + xr) / 2;
if (l <= mid) update(l, r, ls(x), xl, mid, val);
if (mid <= r) update(l, r, rs(x), mid + 1, xr, val);
pushup(x);
}
int query(int l, int r, int x, int xl, int xr) {
if (xl >= l && r >= xr) return tree[x];
pushdown(x, xl, xr);
int res = 0;
int mid = (xl + xr) / 2;
if (l <= mid) res += query(l, r, ls(x), xl, mid);
if (mid <= r) res += query(l, r, rs(x), mid + 1, xr);
pushup(x);
return res;
}
signed main() {
cin >> n >> q;
for (int i = 1; i <= n; i++) cin >> a[i];
build(1, 1, n);
while (q--) {
int op;
cin >> op;
if (op == 1) {
int l, r, val;
cin >> l >> r >> val;
update(l, r, 1, 1, n, val);
} else if (op == 2) {
int l, r;
cin >> l >> r;
cout << query(l, r, 1, 1, n) << "\n";
}
}
return 0;
}
今天是植树节,一群大佬秀出了自己的数据结构,而我连线段树都不会 /kel
调过了!!!
友情提醒 qry 的时候是不用 pushup 的,因为 qry 时子结点的值刚才用父结点的标记更新,本质上没有做出改变。可以减小常数。
确实我也是这样的