#include <bits/stdc++.h>
using namespace std;
/*
第一行n, m, 表示数的个数以及操作数
第二行表示n个数
剩下m行, 每行x, y, z表示操作(1:表示将第y个数加z; 2:求[y, z]区间和)
用线段树, 下面是线段数的模板(单点修改, 区间求和)
*/
int n, m;
int ans = 0;
int he = 0; // 表示线段数中的节点数
int input[500010];
struct node {
int l, r, n;
}tree[2000010];
void build(int l, int r, int idx) { //构建线段树, 填充[l, r]之间的节点, 每一个节点记录的是一个区间的左界与右界
he++;
tree[idx].l = l;
tree[idx].r = r;
if(l == r) return;
int mid = l + r >> 1;
build(l, mid, idx << 1); //递归求下一层的区间, 以中间点为界限分为左右两个区间
build(mid + 1, r, (idx << 1) + 1);
}
int add(int idx) { //填充线段树, 将待处理数据填入线段树
if(tree[idx].l == tree[idx].r) {
tree[idx].n = input[tree[idx].l];
return tree[idx].n;
}
tree[idx].n = add(idx << 1) + add((idx << 1) + 1);
return tree[idx].n;
}
void my_plus(int cur, int idx, int k) { //单点修改, cur表示当前的节点, idx表示需要修改的节点
tree[cur].n += k;
if(tree[cur].l == tree[cur].r) return; //修改到最后的单点区间了, 即所有需要修改的区间修改完毕
if(idx <= tree[cur << 1].r) {
my_plus(cur << 1, idx, k);
}
if(idx >= tree[(cur << 1) + 1].l) {
my_plus((cur << 1) + 1, idx, k);
}
}
void search(int idx, int l, int r) { //[l, r]区间求和
if(tree[idx].l >= l && tree[idx].r <= r) {
ans += tree[idx].n;
return;
}
if(tree[(idx << 1) + 1].l <= r) {
search((idx << 1) + 1, l, r);
}
if(tree[idx << 1].r >= l) {
search(idx << 1, l, r);
}
}
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> input[i];
build(1, n, 1);
add(1);
while(m--) {
int x, y, z;
cin >> x >> y >> z;
if(x == 1) {
my_plus(1, y, z);
}
if(x == 2) {
ans = 0;
search(1, y, z);
cout << ans << endl;
}
}
return 0;
}
线段树之单点修改、区间求和的模板
最新推荐文章于 2024-06-15 23:36:03 发布