loj2512 [BJOI2018]链上二次求和
分析
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define int long long
const int mod = 1e9+7;
const int t = 5e8+4;
int n,m,p[200100],pp[200100],d[20000100],Ans,f1[200100],f2[200100];
int cola[20000100],colb[20000100],colc[20000100];
inline void build(int le,int ri,int wh){
if(le==ri){
d[wh]=pp[le]*2%mod;
return;
}
int mid=(le+ri)>>1;
build(le,mid,wh<<1);
build(mid+1,ri,wh<<1|1);
d[wh]=(d[wh<<1]+d[wh<<1|1])%mod;
}
inline int S(int le,int ri,int a,int b,int c){
int res=c*(ri-le+1)%mod+b*((f1[ri]-(le?f1[le-1]:0)+mod)%mod)%mod
+a*((f2[ri]-(le?f2[le-1]:0)+mod)%mod)%mod;
return res%mod;
}
inline void pd(int wh,int le,int mid,int ri){
int a=cola[wh],b=colb[wh],c=colc[wh];
if(!a&&!b&&!c)return;
cola[wh<<1]+=a,colb[wh<<1]+=b,colc[wh<<1]+=c;
cola[wh<<1]%=mod,colb[wh<<1]%=mod,colc[wh<<1]%=mod;
d[wh<<1]+=S(le,mid,a,b,c);
d[wh<<1]%=mod;
cola[wh<<1|1]+=a,colb[wh<<1|1]+=b,colc[wh<<1|1]+=c;
cola[wh<<1|1]%=mod,colb[wh<<1|1]%=mod,colc[wh<<1|1]%=mod;
d[wh<<1|1]+=S(mid+1,ri,a,b,c);
d[wh<<1|1]%=mod;
cola[wh]=colb[wh]=colc[wh]=0;
}
inline void update(int le,int ri,int wh,int x,int y,int a,int b,int c){
if(le>=x&&ri<=y){
cola[wh]+=a,colb[wh]+=b,colc[wh]+=c;
cola[wh]%=mod,colb[wh]%=mod,colc[wh]%=mod;
d[wh]+=S(le,ri,a,b,c);
d[wh]%=mod;
return;
}
int mid=(le+ri)>>1;
pd(wh,le,mid,ri);
if(mid>=x)update(le,mid,wh<<1,x,y,a,b,c);
if(mid<y)update(mid+1,ri,wh<<1|1,x,y,a,b,c);
d[wh]=(d[wh<<1]+d[wh<<1|1])%mod;
}
inline int q(int le,int ri,int wh,int x,int y){
if(le>=x&&ri<=y)return d[wh];
int mid=(le+ri)>>1,ans=0;
pd(wh,le,mid,ri);
if(mid>=x)ans=(ans+q(le,mid,wh<<1,x,y))%mod;
if(mid<y)ans=(ans+q(mid+1,ri,wh<<1|1,x,y))%mod;
d[wh]=(d[wh<<1]+d[wh<<1|1])%mod;
return ans;
}
signed main(){
int i,j,k;
scanf("%lld%lld",&n,&m);
for(i=1;i<=n;i++)scanf("%lld",&p[i]),p[i]=(p[i]+p[i-1])%mod;
for(i=1;i<=n;i++)pp[i]=(pp[i-1]+p[i])%mod;
for(i=1;i<=n;i++)f1[i]=(f1[i-1]+i)%mod,f2[i]=(f2[i-1]+i*i)%mod;
build(0,n,1);
for(i=1;i<=m;i++){
scanf("%lld",&k);
int le,ri,len,D;
if(k==1){
scanf("%lld%lld%lld",&le,&ri,&D);
if(le>ri)swap(le,ri);
len=ri-le+1;
int a=D,b=(3-2*le%mod+mod)%mod*D%mod;
int c=(le*le%mod-3*le%mod+2+mod)%mod*D%mod;
update(0,n,1,le,ri,a,b,c);
if(ri==n)continue;
a=0,b=2*len*D%mod,c=(len*(len+1-2*ri)%mod+mod)%mod*D%mod;
update(0,n,1,ri+1,n,a,b,c);
}else {
scanf("%lld%lld",&le,&ri);
len=ri-le+1;
Ans=len*q(0,n,1,n,n)%mod;
Ans=(Ans-q(0,n,1,le-1,ri-1)+mod)%mod;
Ans=(Ans-q(0,n,1,n-ri,n-le)+mod)%mod;
printf("%lld\n",Ans*t%mod);
}
}
return 0;
}