线段树模板

送分小仙女□ 提交于 2019-12-01 05:05:19

用于解决RMQ问题,即多次询问

#include <cstdio>
const int MAXN = 100010;
typedef long long LL;

LL num[MAXN<<2];
LL tag[MAXN<<2];

inline void build(int o, int l, int r) {
    tag[o] = 0;
    if (l == r) {
        scanf("%d", &num[o]);
        return;
    }
    int mid = (l + r) >> 1;
    build(o<<1, l, mid);
    build(o<<1|1, mid+1, r);
    num[o] = num[o<<1] + num[o<<1|1];
} 

inline void pushdown(int x, int len) {
    if (tag[x]) {
        tag[x<<1] += tag[x];
        tag[x<<1|1] += tag[x];
        num[x<<1] += tag[x] * (len - (len>>1));
        num[x<<1|1] += tag[x] * (len>>1);
        tag[x] = 0;
    }
}

inline void add(int o, int l, int r, int x, int y, int z) {
    if (x <= l && r <= y) {
        tag[o] += z;
        num[o] += (LL)z * (r - l + 1);
        return;
    }
    pushdown(o, r - l + 1);
    int mid = (l + r) >> 1;
    if (x <= mid) add(o<<1, l, mid, x, y, z);
    if (mid < y) add(o<<1|1, mid+1, r, x, y, z);
    num[o] = num[o<<1] + num[o<<1|1];
}

inline LL query (int o, int l, int r, int x, int y) {
    //大括号不换行
    if (x <= l && r <= y) {
        return num[o];
    }
    pushdown(o, r - l + 1);
    LL ans = 0;
    int mid = (l + r) >> 1;
    if (x <= mid) ans += query(o<<1, l, mid, x, y);
    if (mid < y) ans += query(o<<1|1, mid+1, r, x, y);
    return ans;
} 

int main() {
    int N,Q;
    scanf("%d%d", &N, &Q);
    build(1,1,N);
    int l,r;
    int OP;
    while (Q--) {
        scanf("%d", &OP);
        if(OP == 1) {
            int z;
            scanf("%d%d%d", &l, &r, &z);
            add(1, 1, N, l, r, z);
        }
        else {
            scanf("%d%d", &l, &r);
            printf("%lld\n", query(1, 1, N, l, r));
        }
    }
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!