acommonman @ 2024-12-10 21:27:01
#include<bits/stdc++.h>
using namespace std;
//凡涉及区间一律左闭右开
#define lc p<<1
#define rc p<<1|1
const int N = 1e5 + 3;
int n, m, a[N];
struct node{
int l, r, sum;
int lz = 0;//lazy懒标记,优化区间修改操作
}tr[4 * N];
void pushup(int p){//向上更新(往回走)
tr[p].sum = tr[lc].sum + tr[rc].sum;
}
void pushdown(int p){//懒标记下传
int lz = tr[p].lz;
if(lz){//如果标记为懒
tr[lc].sum += lz * (tr[lc].r - tr[lc].l + 1),
tr[rc].sum += lz * (tr[rc].r - tr[rc].l + 1);
tr[lc].lz += lz, tr[rc].lz += lz, tr[p].lz = 0;
}
}
void build(int p, int l, int r){//建树
tr[p] = {l, r, a[p], 0};
if(l == r)return ;
int m = l + r >> 1;
build(lc, l, m);
build(rc, m + 1, r);
pushup(p);
}
void UN(int p, int x, int k){//点修改
if(tr[p].l == x && tr[p].r == x){
tr[p].sum += k;
return ;
}
int m = tr[p].l + tr[p].r >> 1;
if(x <= m)UN(lc, x, k);//on the left
else UN(rc, x, k);//on the right
tr[p].sum += k;
}
int query(int p, int l, int r){//区间查询
if(tr[p].l >= l && tr[p].r <= r)return tr[p].sum;//覆盖则返回
int m = tr[p].l + tr[p].r >> 1;
int sum = 0;
if(l <= m)sum += query(lc, l, r);
if(r > m)sum += query(rc, l, r);
return sum;
}
//区间修改 + 懒标记
void UI(int p, int l, int r, int k){//区间修改
if(tr[p].l >= l && tr[p].r <= r){
tr[p].sum += k * (tr[p].r - tr[p].l + 1);
tr[p].lz += k;
return ;
}
pushdown(p);
int m = tr[p].l + tr[p].r >> 1;
if(m >= l)UI(lc, l, r, k);
if(m < r)UI(rc, l, r, k);
pushup(p);
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)scanf("%d", &a[i]);
build(1, 1, n);//建树
for(int i = 1; i <= m; i++){
int num = 0, x, y;
scanf("%d", &num);
if(num == 1){
int z;
scanf("%d%d%d", &x, &y, &z);
UI(1, x, y, z);//区间修改
}else {
scanf("%d%d", &x, &y);
printf("%d\n", query(1, x, y));//区间查询
}
}
return 0;
}
照着别人的模板敲,敲完发现戳了心态炸裂QwQ
by Poole_tea @ 2024-12-10 21:48:01
建树不对,改成这样.另外查询的时候也要下传懒标记
void build(ll p, ll l, ll r){//建树
tr[p] = {l, r, 0, 0};
if(l == r){
tr[p].sum = a[l] ;
return ;
}
ll m = l + r >> 1;
build(lc, l, m);
build(rc, m + 1, r);
pushup(p);
}