//线段树 单点修改 区间查询
#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版权协议,转载请附上原文出处链接和本声明。