题意
很简答就是每次查询 (L,R)的时候 ,查询
思路
我们可以看出
那么我们线段树就维护前缀和的前缀和就行了,对于查询来说,比如说我我们查
代码
#include <bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define int long long
using namespace std;
const int maxn = 1e5+10;
long long a[maxn] , sum[maxn];
long long tree[maxn<<2] ,add[maxn<<2];
struct Tree
{
void pushup(int rt)
{
tree[rt] = tree[rt<<1] + tree[rt<<1|1];
}
void pushdown(int l,int r,int rt)
{
if(!add[rt]) return ;
int m = (l+r)>>1;
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
tree[rt<<1] += add[rt] *(m-l+1);
tree[rt<<1|1] += add[rt] * (r-m);
add[rt] = 0;
}
void build(int l,int r,int rt)
{
if(l == r) {tree[rt] = sum[l] ; return ;}
int m = (l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int L,int R,long long val, int l,int r,int rt)
{
if(l >= L && R >= r)
{
tree[rt] += (r-l+1)*val;
add[rt] += val;
return ;
}
pushdown(l,r,rt);
int m = (l+r)>>1;
if(m >= L) update(L,R,val,lson);
if(m < R) update(L,R,val,rson);
pushup(rt);
}
long long query(int L,int R,int l,int r,int rt)
{
if(l >= L && R >= r) return tree[rt];
pushdown(l,r,rt);
int m = (l+r)>>1;
long long ret = 0 ;
if(m >= L) ret += query(L,R,lson);
if(m < R) ret += query(L,R,rson);
return ret;
}
};
signed main()
{
int n,q;
while(scanf("%lld%lld",&n,&q)!=EOF)
{
memset(sum,0,sizeof(sum));
memset(tree,0,sizeof(tree));
memset(add,0,sizeof(add));
sum[0] = 0;
Tree A;
for(int i = 1 ; i <= n ; i++)
{
scanf("%lld",&a[i]);
sum[i] = sum[i-1] + a[i];
}
A.build(1,n,1);
while(q--)
{
int op,l,r;
scanf("%lld%lld%lld",&op,&l,&r);
if(op == 1)
{
long long ans = 0;
if(l == 1) ans = A.query(l,r,1,n,1);
else
{
ans = A.query(l,r,1,n,1) - (r-l+1) * A.query(l-1,l-1,1,n,1);
}
cout<<ans<<endl;
}
else
{
A.update(l,n,r-a[l],1,n,1);
a[l] = r;
}
}
}
}