新学线段树,求调

P3372 【模板】线段树 1

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);
}

|