需要lazy思想的線段樹
原本都關機睡覺了,來了靈感,雙重維護
聽說過lazy的想法,實現方式是自己想到的,增量+子區間總和
5Y
3*TLE
1*WA
這個可以當做自己的模板了吧~~
TLE的關鍵點在於
insert和sum的結束條件都不能是T[w].l==T[w].r這樣比O(n)的樸素算法還慢..貌似
想要加快sum,需要維護下段總和
想要加快insert,需要維護區間上統一增量
二者缺一不可
在多次實現中和刷牙+思考終於想出...
滿足感滿滿
#include<stdio.h>
#define LL long long
struct line{
int l,r;
LL x,s;
}T[1<<18];
void build(int s,int t,int w){
T[w].l=s;T[w].r=t;
T[w].x=0;T[w].s=0;
if(s==t)return;
int mid=(s+t)/2;
build(s,mid,w*2);
build(mid+1,t,w*2+1);
}
void insert(int s,int t,int w,LL val){
if(T[w].l==s&&T[w].r==t){T[w].x+=val;return;}
T[w].s+=(t+1-s)*val;
int mid=(T[w].l+T[w].r)/2;
if(s>mid)insert(s,t,w*2+1,val);
else if(t<=mid)insert(s,t,w*2,val);
else {
insert(s,mid,w*2,val);
insert(mid+1,t,w*2+1,val);
}
}
LL sum(int s,int t,int w){
LL tp=(t+1-s)*T[w].x;
if(T[w].l==s&&T[w].r==t)return tp+T[w].s;
int mid=(T[w].l+T[w].r)/2;
if(s>mid)return tp+sum(s,t,w*2+1);
else if(t<=mid)return tp+sum(s,t,w*2);
else {
return tp+sum(s,mid,w*2)+sum(mid+1,t,w*2+1);
}
}
int main(){
int N,Q;
while(scanf("%d%d",&N,&Q)!=EOF){
build(1,N,1);
int i,j,s,t;
LL x;
char c;
for(i=1;i<=N;i++){
scanf("%lld%*c",&x);
insert(i,i,1,x);
}
for(i=1;i<=Q;i++){
scanf("%c",&c);
if(c=='Q'){
scanf("%d %d%*c",&s,&t);
printf("%lld\n",sum(s,t,1));
continue;
}
scanf("%d %d %lld%*c",&s,&t,&x);
insert(s,t,1,x);
}
}
return 0;
}