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:
-
If the question type is 11, you should answer how much knowledge he will get after he reads books [ ll, rr ].
-
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)ai .
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, cc represents [ 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
题目来源
ACM-ICPC 2018 徐州赛区网络预赛
参考的别人的思路,自己想不到、、、、
其实这个可以分解为len个前缀和。设sum(l,r)表示l到r的和,则上式等于:
sum(l,l)+sum(l,l+1)+sum(l,l+2)+…+sum(l,r)
=sum(1,l)+sum(1,l+1)+sum(1,l+2)+…+sum(1,r)-(r-l+1)*sum(1,l-1)
则转化为求前缀和的区间和。然后对单点修改,相当于对要修改的位置i到n所有的前缀和都加增量。
也就转化为线段树查询区间和,区间修改。
区间修改用lazy标志即可。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
ll tree[maxn<<2];
ll lazy[maxn<<2];
int n,q;
int ip;
ll fo[maxn];
void build(int l,int r,int node)
{
if(l==r)
{
tree[node]=fo[ip++];
return;
}
ll m=(l+r)>>1;
build(l,m,node*2);
build(m+1,r,node*2+1);
tree[node]=tree[node*2]+tree[node*2+1];
}
ll query(int L,int R,int l,int r,int node,ll z)
{
lazy[node]+=z;
if(L>r||R<l)
{
return 0;
}
if (L <= l && r <= R) {
return tree[node]+lazy[node]*(r-l+1);
}
ll m=(l+r)>>1;
ll ret=0;
ret+=query(L,R,l,m,node*2,lazy[node]);
ret+=query(L,R,m+1,r,node*2+1,lazy[node]);
tree[node]=lazy[node]*(r-l+1);
lazy[node]=0;
return ret;
}
void update(int L,int R,int add,int l,int r,int node)
{
if(l==r)
{
tree[node]+=add;
return;
}
if(L<=l&&R>=r)
{
lazy[node]+=add;
}
ll m=(l+r)>>1;
if(L<=m)
{
update(L,R,add,l,m,node*2);
}
if(R>m)
{
update(L,R,add,m+1,r,node*2+1);
}
tree[node]=tree[node*2]+tree[node*2+1];
}
int main()
{
int co[maxn];
cin>>n>>q;
for(int i=1;i<=n;i++){
scanf("%d",&co[i]);
fo[i]=co[i]+fo[i-1];
}
ip=1;
build(1,n,1);
int l,r,len,v,d,flag;
while(q--)
{
scanf("%d",&flag);
if(flag==1){
scanf("%d%d",&l,&r);
len=r-l+1;
printf("%lld\n",query(l,r,1,n,1,0)-len*query(l-1,l-1,1,n,1,0));
}
else{
scanf("%d%d",&d,&v);
update(d,n,v-co[d],1,n,1);
co[d]=v;
}
}
}