Ryuji doesn't want to study (推導公式+線段樹lazy標記)
- 24.51%
- 1000ms
- 262144K
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
題目來源
雖然可以用樹狀陣列做,但覺得線段樹的方法易於理解(吧)....
其實這個可以分解為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;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define lcvalue(rt) (lz[rt<<1]*(m-l+1)+tree[rt<<1])
#define rcvalue(rt) (lz[rt<<1|1]*(r-m)+tree[rt<<1|1])
#define PushUP(rt) tree[rt] = lcvalue(rt)+ rcvalue(rt)
const int maxn = 1e5+5;
ll tree[maxn<<2];
ll lz[maxn<<2];
int ip;
int n,q;
ll fo[maxn];
void build(int l,int r,int rt) {
if (l == r) {
tree[rt]=fo[ip++];
return ;
}
ll m = (l + r) >> 1;
build(lson);
build(rson);
PushUP(rt);
}
ll query(int L,int R,int l,int r,int rt,ll z){
lz[rt]+=z;
if(L>r || R<l)
return 0;
if (L <= l && r <= R) {
return tree[rt]+lz[rt]*(r-l+1);
}
ll m = (l + r) >> 1;
ll ret = 0;
ret += query(L , R , lson,lz[rt]);
ret += query(L , R , rson,lz[rt]);
tree[rt]+=lz[rt]*(r-l+1);
lz[rt]=0;
return ret;
}
void update(int L,int R,ll add,int l,int r,int rt) {
if (l == r) {
tree[rt] += add;
return ;
}
if (L <= l && r <= R) {
lz[rt]+=add;
return;
}
ll m = (l + r) >> 1;
if (L <= m) update(L,R, add , lson);
if(R>m) update(L,R, add , rson);
PushUP(rt);
}
int co[maxn];
int main(){
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;
}
}
}