- 题解
线段树模板
- @ 2026-8-7 10:24:27
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5, mod = 1e9+7;
int a[N], n, q;
int tr[N*4], tag[N*4];
void build(int k, int l, int r){ // 第k个点,维护[l, r]
if(l == r) { // 叶子结点
tr[k] = a[l];// 区间只有一个数
return ;
}
int mid = l + r >> 1;
build(k*2, l, mid);
build(k*2+1, mid+1, r);
tr[k] = tr[k*2] + tr[k*2+1];
}
void upd(int k, int l, int r, int w){
tr[k] += w * (r - l + 1);
tag[k] += w;
}
void pushdown(int k, int l, int r){
// tag[k]
int mid = l + r >> 1;
upd(k*2, l, mid, tag[k]);
upd(k*2+1, mid+1, r, tag[k]);
tag[k] = 0;
}
int query(int k, int l, int r, int x, int y){
// 第k个点,维护[l, r]。 查询区间 [x, y]
if(x <= l && r <= y){
return tr[k];
}
pushdown(k, l, r);
int mid = l + r >> 1;
int ans = 0;
if(x <= mid) { // 与左孩子有重叠
ans += query(k*2, l, mid, x, y);
}
if(y > mid){
ans += query(k*2+1, mid+1, r, x, y);
}
return ans;
}
void modify(int k, int l, int r, int x, int y, int w){
//第k个点,维护[l, r], 修改[x, y] 增加 w
if(x <= l && r <= y){
tr[k] += w * (r - l + 1);
tag[k] += w; // upd(k);
return ;
}
pushdown(k, l, r);
int mid = l + r >> 1;
if(x <= mid) modify(k*2, l, mid, x, y, w);
if(y > mid) modify(k*2+1, mid+1, r, x, y, w);
tr[k] = tr[k*2] + tr[k*2+1];
} // O(n)
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> q;
for(int i = 1; i <= n; i++) cin >> a[i];
build(1, 1, n);
while(q--){
int op, l, r;
cin >> op >> l >> r;
if(op == 1) {
int w;
cin >> w;
modify(1, 1, n, l, r, w);
} else {
cout << query(1, 1, n, l, r) << "\n";
}
}
return 0;
}
0 条评论
目前还没有评论...