线段树 模板一:单点修改 区间查询

模板题链接

//线段树 单点修改 区间查询
#include <bits/stdc++.h>
#define int long  long
using namespace std;
const int N = 1e5 + 7;
int n, m, a[N];
struct node {
    int l, r, sum;   //一条线段 边界 值
};
struct segment_tree {
    node t[N << 2];  //节点 一般开四倍容量
    int mp[N];       //记录叶子节点的标号

    //往上合并线段的值
    void push_up(int root) {
        int h = root << 1;
        t[root].sum = t[h].sum + t[h + 1].sum;
    }

    //递归建树
    void build(int root, int l, int r) {
        t[root].l = l;
        t[root].r = r;
        if(l != r) {
            int mid = (l + r) >> 1;
            int h = root << 1;
            build(h, l, mid);
            build(h + 1, mid + 1, r);
            push_up(root);      //线段值的合并
        } else {
            t[root].sum = a[l];
            mp[l]  = root;      //记录当前叶子节点的编号
        }
    }
    
    int query(int root, int  l, int r) {
        if(t[root].l == l && t[root].r == r) {
            return t[root].sum;
        }
        int mid = (t[root].l + t[root].r) >> 1;
        int h = root << 1;

        if(r <= mid) return query(h, l, r);
        else if(l > mid) return query(h + 1, l, r);
        else return query(h, l, mid) + query(h + 1, mid + 1, r);
    }

    void change(int x, int y) {
        x = mp[x];
        t[x].sum += y;
        while(x >>= 1) push_up(x);
    }
};
segment_tree ST;

signed main() {
    scanf("%lld %lld", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);

    ST.build(1, 1, n);


    for(int op, x, y, i = 0; i < m; i++) {
        scanf("%lld%lld%lld", &op, &x, &y);
        if(op == 1) {
            ST.change(x, y);
        }
        if(op == 2) {
            int ok = ST.query(1, x, y);
            printf("%lld\n", ok);
        }
    }

    return 0;
}

版权声明:本文为weixin_51552756原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。