线段树
①建树---o(n)
②单点修改---o(logn)
③区间查询---o(logn)
④区间修改---o(logn)
//线段树
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define lc p<<1
#define rc p<<1|1
const int N=500005;
int n,arr[N];
typedef struct node{
int l,r,sum,add; //区间修改还需要第四个变量add,表示标记
}node;
node tree[4*N];
void build(int p,int l,int r){ //根节点 和 区间的左右边界 o(n)
tree[p]={l,r,arr[l]};
if(l==r) return; //是叶子节点则返回
int mid=l+(r-l)/2;
build(p<<1,l,mid); //p<<1 == p*2
build(p<<1|1,mid+1,r); //p<<1|1 == p*2+1
tree[p].sum=tree[ p<<1 ].sum+tree[ p<<1|1 ].sum; //父节点的sum 等于 左右孩子的sum 的和
}
void update1(int p,int x,int k){ //单点修改 //根节点p 修改位置x 增加的值k o(logn)
if(tree[p].l==x&&tree[p].r==x){ //找到修改位置x
tree[p].sum+=k;
return;
}
int mid=tree[p].l+( tree[p].r-tree[p].l )/2;
if(x<=mid) update1( p<<1,x,k );
if(x>mid) update1( p<<1|1,x,k );
tree[p].sum=tree[ p<<1 ].sum+tree[ p<<1|1 ].sum;
}
int query(int p,int x,int y){ //根节点p 查询区间[x,y]的值 o(logn)
if(x<=tree[p].l&&tree[p].r<=y) return tree[p].sum; //完全覆盖则返回
int mid=tree[p].l+( tree[p].r-tree[p].l )/2;
int sum=0;
if(x<=mid) sum+=query( p<<1,x,y ); //与左子树重叠就递归访问左子树
if(y>mid) sum+=query( p<<1|1,x,y ); //与右子树重叠就递归访问右子树
return sum;
}
//区间修改! o(logn)
void pushup(int p){ //向上更新
tree[p].sum=tree[lc].sum+tree[rc].sum;
}
void pushdown(int p){ //向下更新
if(tree[p].add){ //非0
tree[lc].sum+=tree[p].add*( tree[lc].r-tree[lc].l+1 ); //左孩子区间宽度*k
tree[rc].sum+=tree[p].add*( tree[rc].r-tree[rc].l+1 ); //右孩子区间宽度*k
tree[lc].add+=tree[p].add;
tree[rc].add+=tree[p].add;
tree[p].add=0;
}
}
void update2(int p,int x,int y,int k){ //根节点p 修改的区间[x,y] 增加的值k
if(x<=tree[p].l&&tree[p].r<=y){ //完全覆盖则修改
tree[p].sum+=( tree[p].r-tree[p].l+1 )*k; //区间宽度*k
tree[p].add+=k; //标记
return;
}
int mid=( tree[p].l+tree[p].r )>>1; //不覆盖则裂开
pushdown(p);
if(x<=mid) update2(lc,x,y,k);
if(y>mid) update2(rc,x,y,k);
pushup(p);
}
void solve(){ //线段树模板
int m;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>arr[i];
build(1,1,n);
while(m--){
int op;
cin>>op;
if(op==1){
int x,k;
cin>>x>>k;
update1(1,x,k);
}
else{
int x,y;
cin>>x>>y;
cout<<query(1,x,y)<<"\n";
}
}
}
signed main() {
ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
solve();
return 0;
}