传送门:bzoj5291
设 S S S为 a a a的前缀和, S S SS SS为 S S S的前缀和。
每次询问所求 ∑ k = l r ∑ i = k n ( S i − S i − k ) \sum\limits_{k=l}^r\sum\limits_{i=k}^{n}(S_i-S_{i-k}) k=l∑ri=k∑n(Si−Si−k)可化简为:
( r − l + 1 ) S S n − ∑ i = l − 1 r − 1 S S i − ∑ i = n − r n − l S S i (r-l+1)SS_n-\sum\limits_{i=l-1}^{r-1}SS_i-\sum\limits_{i=n-r}^{n-l}SS_i (r−l+1)SSn−i=l−1∑r−1SSi−i=n−r∑n−lSSi
这是一个关于 i i i的二元一次函数,可以化成 a i 2 + b i + c ai^2+bi+c ai2+bi+c的形式用线段树维护标记下传。
#include
#define mid ((l+r)>>1)
#define lc k<<1
#define rc k<<1|1
using namespace std;
const int N=2e5+10,mod=1e9+7;
const int iv2=5e8+4;
typedef long long ll;
int n,m,a[N],pa[N],pb[N];
char cp,OS[100];
inline void rd(int &x)
{
cp=getchar();x=0;
for(;!isdigit(cp);cp=getchar());
for(;isdigit(cp);cp=getchar()) x=(x<<3)+(x<<1)+(cp^48);
}
inline void ot(int x)
{
int re=0;OS[0]='\n';
for(;(!re)||(x);x/=10) OS[++re]='0'+x%10;
for(;~re;--re) putchar(OS[re]);
}
inline int ad(int x,int y){x+=y;return x>=mod?x-mod:x;}
inline int dc(int x,int y){x-=y;return x<0?x+mod:x;}
struct node{
int s,a,b,c;
inline void chg(node x,int l,int r)
{
if(x.a) a=ad(a,x.a),s=ad(s,(ll)x.a*dc(pa[r],pa[l-1])%mod);
if(x.b) b=ad(b,x.b),s=ad(s,(ll)x.b*dc(pb[r],pb[l-1])%mod);
if(x.c) c=ad(c,x.c),s=ad(s,(ll)x.c*(r-l+1)%mod);
}
inline void mul(int z){a=(ll)a*z%mod;b=(ll)b*z%mod;c=(ll)c*z%mod;}
}t[N<<2],tp;
void build(int k,int l,int r)
{
if(l==r) {t[k].s=a[l];return;}
build(lc,l,mid);build(rc,mid+1,r);
t[k].s=ad(t[lc].s,t[rc].s);
}
inline void pushdown(int k,int l,int r)
{
if((!t[k].a)&&(!t[k].b)&&(!t[k].c)) return;
t[lc].chg(t[k],l,mid);t[rc].chg(t[k],mid+1,r);
t[k].a=t[k].b=t[k].c=0;
}
void ad(int k,int l,int r,int L,int R)
{
if(L<=l && r<=R){t[k].chg(tp,l,r);return;}
pushdown(k,l,r);
if(L<=mid) ad(lc,l,mid,L,R);
if(R>mid) ad(rc,mid+1,r,L,R);
t[k].s=ad(t[lc].s,t[rc].s);
}
int ask(int k,int l,int r,int L,int R)
{
if(L<=l && r<=R) return t[k].s;
pushdown(k,l,r);
if(R<=mid) return ask(lc,l,mid,L,R);
if(L>mid) return ask(rc,mid+1,r,L,R);
return ad(ask(lc,l,mid,L,R),ask(rc,mid+1,r,L,R));
}
int main(){
int i,op,x,y,z,re;
rd(n);rd(m);
for(i=1;i<=n;++i) {rd(a[i]);a[i]=ad(a[i],a[i-1]);}
for(i=2;i<=n;++i) a[i]=ad(a[i],a[i-1]);
for(i=1;i<=n;++i) {pb[i]=ad(pb[i-1],i);pa[i]=ad(pa[i-1],(ll)i*i%mod);}
build(1,1,n);
for(;m;--m){
rd(op);rd(x);rd(y);if(x>y) swap(x,y);
if(op==1){
tp=(node){0,iv2,(ll)dc(3,ad(x,x))*iv2%mod,(ll)dc(ad((ll)x*x%mod,2),(ll)3*x%mod)*iv2%mod};
rd(z);tp.mul(z);ad(1,1,n,x,y);
if(y1) z=ask(1,1,n,max(1,x-1),y-1);
if(n>x) z=ad(z,ask(1,1,n,max(1,n-y),n-x));
ot(dc(re,z));
}
}
return 0;
}