Ryuji is not a good student, and he doesn't want to study. But there are n books he should learn, each book has its knowledge a[i]a[i].
Unfortunately, the longer he learns, the fewer he gets.
That means, if he reads books from ll to rr, he will get a[l] \times L + a[l+1] \times (L-1) + \cdots + a[r-1] \times 2 + a[r]a[l]×L+a[l+1]×(L−1)+⋯+a[r−1]×2+a[r] (LL is the length of [ ll, rr ] that equals to r - l + 1r−l+1).
Now Ryuji has qq questions, you should answer him:
11. If the question type is 11, you should answer how much knowledge he will get after he reads books [ ll, rr ].
22. If the question type is 22, Ryuji will change the ith book's knowledge to a new value.
Input
First line contains two integers nn and qq (nn, q \le 100000q≤100000).
The next line contains n integers represent a[i]( a[i] \le 1e9)a[i](a[i]≤1e9) .
Then in next qq line each line contains three integers aa, bb, cc, if a = 1a=1, it means question type is 11, and bb, ccrepresents [ ll , rr ]. if a = 2a=2 , it means question type is 22 , and bb, cc means Ryuji changes the bth book' knowledge to cc
Output
For each question, output one line with one integer represent the answer.
样例输入复制
5 3 1 2 3 4 5 1 1 3 2 5 0 1 4 5
样例输出复制
10 8
题目来源
线段树
先把前缀和存下来,在更新和查询
#include<map>
#include<stack>
#include<queue>
#include<math.h>
#include<vector>
#include<string>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#define mem(a,b) memset(b,sizeof(a),b)
#define LL long long
#define inf 0x3f3f3f
#define root 1,n,1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define lcvalue(rt) (lazy[rt<<1]*(mid-l+1)+sum[rt<<1])
#define rcvalue(rt) (lazy[rt<<1|1]*(r-mid)+sum[rt<<1|1])
#define PushUp(rt) sum[rt] = lcvalue(rt)+ rcvalue(rt)
using namespace std;
const int maxn=100115;
LL sum[maxn<<2];
LL lazy[maxn<<2];
int n,m,p;
LL a[maxn],b[maxn];
void Build(int l,int r,int rt)//建树
{
if(l==r){
sum[rt]=b[p++];
return ;
}
int mid=(l+r)>>1;
Build(lson);//建左儿子
Build(rson);//右儿子
PushUp(rt);//更新
}
void Update(int ll,int rr,LL c,int l,int r,int rt)//区间更新
{
if(l==r){
sum[rt]+=c;return ;
}
if(ll<=l&&rr>=r)//找到相应区间直接返回sum
{
lazy[rt]+=c;
return ;
}
int mid=(l+r)>>1;
if(ll<=mid) Update(ll,rr,c,lson);//在左儿子中找区间
if(rr>mid) Update(ll,rr,c,rson);//在右儿子中找
PushUp(rt);//向上更新sum;
}
LL Query(int ll,int rr,int l,int r,int rt,LL z)//区间查询
{
//cout<<ll<<" "<<rr<<" "<<l<<" "<<r<<" "<<rt<<" "<<z<<endl;
lazy[rt]+=z;
if(ll>r||rr<l)return 0;
if(ll<=l&&rr>=r)return sum[rt]+(r-l+1)*lazy[rt];
LL cnt=0;
int mid=(l+r)/2;
cnt+=Query(ll,rr,lson,lazy[rt]);
cnt+=Query(ll,rr,rson,lazy[rt]);
sum[rt]+=(r-l+1)*lazy[rt];
lazy[rt]=0;
return cnt;//返回区间的和
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
mem(a,0);mem(b,0);mem(sum,0);mem(lazy,0);
p=1;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
b[i]=a[i]+b[i-1];
}
Build(root);
for(int i=0;i<m;i++){
LL x,y,z;
scanf("%lld%lld%lld",&x,&y,&z);
if(x==1){
LL ans=0;
//if(y!=1)
ans=(z-y+1)*Query(y-1,y-1,root,0);
printf("%lld\n",Query(y,z,root,0)-ans);
}
else {
Update(y,n,z-a[y],root);
a[y]=z;
}
}
}
}