大家好,今天来一道线段树的题目。
1.题面
相连的宇宙
题目背景
闪亮星挑战第二天。天空万里无云,是观测的好天气。
如果继续确认拍摄的数据,就会发现像未知的小行星一样的天体。
大家非常紧张。这次真的是最后的机会,再次开始拍摄。
题目描述
苍很可爱,所以她给出了一个序列 (a) 和一些操作:
(0 l r s t) :在 (a_l sim a_r) 中的每个数依次加上一个首项为 (s) ,公差为 (k) 的等差数列。
(1 l r) :查询 $ sum_{i=l}^r a_i^{2} mod ( 1 imes 10^9 + 7 ) $ 。
输入格式
第一行两个整数 (n,m) 表示序列长 (n) ,有 (m) 个操作。
第二行 (n) 个整数,表示开始时序列中的元素。
接下来 (m) 行,每行若干数,其中第一个数为 (opt) 表示操作编号。
输出格式
对于每个 (1) 操作输出一个答案,每个答案占一行。
输入输出样例
样例输入
5 3
0 0 0 0 0
0 1 5 1 1
0 1 3 0 1
1 1 5
样例输出
76
数据范围
对于 (30\%) 的数据 $1 leq n,m leq 1 imes 10^{3} $ 。
对于另外 (20\%) 的数据 $ l = 1 , r=n$ 。
对于另外 (20\%) 的数据 (s=1 , k=1 , a_i=1)。
对于 (100\%) 的数据 (1 leq lleq rleq nleq 1 imes 10^{5} , 1leq mleq 1 imes 10^{5} , |s| , |k| , |a_i| leq 1 imes 10^{9})。
特别提示
2.解法
先完成以上两题,这道题也就很简单了。(这两道题是开启这道题的钥匙。)
我们可以推一下式子,比如现在我们对1到N加上一个等差数列后的总和。
(sum_{i=1}^n (a_i+s+(i-1) imes k)^{2})
(Longleftrightarrow sum_{i=1}^{n} a_i^{2}+(s+(i-1) imes k)^{2}+2 imes a_i imes (s+(i-1) imes k))
(Longleftrightarrow sum_{i=1}^{n} a_i^{2}+s^2+(i-1)^{2}k^{2}+2s(i-1)k+2a_is+2a_i(i-1)k)
(Longleftrightarrow ns^2+dfrac{n(n-1)(2n-1)}{6}k^2 +(n-1)nsk+sum_{i=1}^{n}2a_is+sum_{i=1}^{n} 2a_i(i-1)k+ sum_{i=1}^{n} a_i^{2})
(Longleftrightarrow ns^2+dfrac{n(n-1)(2n-1)}{6}k^2 +(n-1)nsk+2ssum_{i=1}^{n}a_i+2ksum_{i=1}^{n} a_i(i-1)+ sum_{i=1}^{n} a_i^{2})
那么我们就用线段树来处理三种元素, (T1) 记录 (a_i^{2}) , (T2) 记录 (a_i(i-1)) , (T3) 记录 (a_i) 。
$Longleftrightarrow ns^{2} + dfrac{n(n-1)(2n-1)}{6}k^2 + (n-1)nsk + 2sT3 + 2kT2 + T1 $
然后用 (TagS) 记录首项, (TagK) 记录差量。
最后在标记下传函数和修改函数稍微注意一下细节,记得取模就行啦。
3.代码
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<iostream>
#define INF 1LL<<62;
#define ll long long
#define For(X,From,To) for(ll X=From;X<=To;X++)
using namespace std;
const ll MAXN=1e5+5;
const ll Mod=1e9+7;
ll N,M,Opt,X,Y,S,K,A[MAXN],T1[MAXN*4],T2[MAXN*4],T3[MAXN*4],Tag1[MAXN*4],Tag2[MAXN*4];
ll QP(ll B,ll K,ll Mod){ ll Ans=1;for(;K;K>>=1,B=B*B%Mod) if(K&1) Ans=Ans*B%Mod;return Ans;}
template<class T>void Read(T &X){
X=0; ll F=0;char Ch=getchar();
while(Ch<'0' || Ch>'9'){ F|=(Ch=='-');Ch=getchar();}
while(Ch>='0' && Ch<='9'){ X=X*10+(Ch^48);Ch=getchar();}
X=F? -X:X;
}
void Update(ll P,ll L,ll R){
ll Mid=(L+R)>>1;
T1[P]=(T1[P<<1]+T1[(P<<1)|1])%Mod;
T2[P]=(T2[P<<1]+T2[(P<<1)|1]+(Mid-L+1)*T3[(P<<1)|1]%Mod)%Mod;
T3[P]=(T3[P<<1]+T3[(P<<1)|1])%Mod;
}
void Build(ll P,ll L,ll R){
if(L==R){
T1[P]=(A[L]*A[L])%Mod;
T2[P]=0;
T3[P]=A[L];
return;
}
ll Mid=(L+R)>>1;
Build(P<<1,L,Mid);Build((P<<1)|1,Mid+1,R);
Update(P,L,R);
}
void Down(ll P,ll L,ll R){
ll Mid=(L+R)>>1;
Tag1[P<<1]=(Tag1[P<<1]+Tag1[P])%Mod;
Tag1[(P<<1)|1]=(Tag1[(P<<1)|1]+Tag1[P]+(Mid-L+1)*Tag2[P])%Mod;
Tag2[P<<1]=(Tag2[P<<1]+Tag2[P])%Mod;
Tag2[(P<<1)|1]=(Tag2[(P<<1)|1]+Tag2[P])%Mod;
ll Len=(Mid-L+1);
T1[P<<1]=(T1[P<<1]+Len*Tag1[P]%Mod*Tag1[P]%Mod+(Len-1)*Len%Mod*(2*Len-1)%Mod*QP(6,Mod-2,Mod)%Mod*Tag2[P]%Mod*Tag2[P]%Mod+(Len-1)*Len%Mod*Tag1[P]%Mod*Tag2[P]%Mod+2*T3[P<<1]%Mod*Tag1[P]%Mod+T2[P<<1]*2%Mod*Tag2[P]%Mod)%Mod;
T2[P<<1]=(T2[P<<1]+(Len-1)*Len%Mod*QP(2,Mod-2,Mod)%Mod*Tag1[P]%Mod+Len*(Len-1)*(2*Len-1)%Mod*QP(6,Mod-2,Mod)%Mod*Tag2[P]%Mod)%Mod;
T3[P<<1]=(T3[P<<1]+Len*Tag1[P]+(Len-1)*Len%Mod*QP(2,Mod-2,Mod)%Mod*Tag2[P]%Mod)%Mod;
Tag1[P]=(Tag1[P]+(Mid-L+1)*Tag2[P]%Mod)%Mod;
Len=R-Mid;
T1[(P<<1)|1]=(T1[(P<<1)|1]+Len*Tag1[P]%Mod*Tag1[P]%Mod+(Len-1)*Len%Mod*(2*Len-1)%Mod*QP(6,Mod-2,Mod)%Mod*Tag2[P]%Mod*Tag2[P]%Mod+(Len-1)*Len%Mod*Tag1[P]%Mod*Tag2[P]%Mod+2*T3[(P<<1)|1]%Mod*Tag1[P]%Mod+T2[(P<<1)|1]*2%Mod*Tag2[P]%Mod)%Mod;
T2[(P<<1)|1]=(T2[(P<<1)|1]+(Len-1)*Len%Mod*QP(2,Mod-2,Mod)%Mod*Tag1[P]%Mod+Len*(Len-1)*(2*Len-1)%Mod*QP(6,Mod-2,Mod)%Mod*Tag2[P]%Mod)%Mod;
T3[(P<<1)|1]=(T3[(P<<1)|1]+Len*Tag1[P]+(Len-1)*Len%Mod*QP(2,Mod-2,Mod)%Mod*Tag2[P]%Mod)%Mod;
Tag1[P]=0;Tag2[P]=0;
}
void Change(ll P,ll L,ll R,ll X,ll Y,ll S,ll K){
if(L==X && R==Y){
Tag1[P]=(Tag1[P]+S)%Mod;
Tag2[P]=(Tag2[P]+K)%Mod;
ll Len=R-L+1;
T1[P]=(T1[P]+Len*S%Mod*S%Mod+(Len-1)*Len*(2*Len-1)%Mod*QP(6,Mod-2,Mod)%Mod*K%Mod*K%Mod+(Len-1)*Len%Mod*S%Mod*K%Mod+2*T3[P]%Mod*S%Mod+T2[P]*2%Mod*K%Mod)%Mod;
T2[P]=(T2[P]+(Len-1)*Len%Mod*QP(2,Mod-2,Mod)%Mod*S%Mod+Len*(Len-1)%Mod*(2*Len-1)%Mod*QP(6,Mod-2,Mod)%Mod*K%Mod)%Mod;
T3[P]=(T3[P]+Len*S+(Len-1)*Len%Mod*QP(2,Mod-2,Mod)%Mod*K%Mod)%Mod;
return;
}
Down(P,L,R);
ll Mid=(L+R)>>1;
if(Y<=Mid) Change(P<<1,L,Mid,X,Y,S,K);
else if(X>Mid) Change((P<<1)|1,Mid+1,R,X,Y,S,K);
else{
Change(P<<1,L,Mid,X,Mid,S,K);
Change((P<<1)|1,Mid+1,R,Mid+1,Y,(S+(Mid-X+1)*K)%Mod,K);
}
Update(P,L,R);
}
ll Qurey(ll P,ll L,ll R,ll X,ll Y){
if(L==X && R==Y) return T1[P]%Mod;
Down(P,L,R);
ll Mid=(L+R)>>1;
if(Y<=Mid) return Qurey(P<<1,L,Mid,X,Y)%Mod;
else if(X>Mid) return Qurey((P<<1)|1,Mid+1,R,X,Y)%Mod;
else return (Qurey(P<<1,L,Mid,X,Mid)+Qurey((P<<1)|1,Mid+1,R,Mid+1,Y))%Mod;
}
int main(){
freopen("T4.in","r",stdin);
freopen("T4.out","w",stdout);
Read(N);Read(M);
For(i,1,N) Read(A[i]);
Build(1,1,N);
while(M--){
Read(Opt);Read(X);Read(Y);
if(Opt==0){
Read(S);Read(K);
Change(1,1,N,X,Y,S,K);
}else printf("%lld
",(Qurey(1,1,N,X,Y)+Mod)%Mod);
}
return 0;
}