相连的宇宙 题解
大家好,今天来一道线段树的题目。
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 \times 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 \times 10^{3} $ 。
对于另外 \(20\%\) 的数据 $ l = 1\ ,\ r=n$ 。
对于另外 \(20\%\) 的数据 \(s=1\ ,\ k=1\ ,\ a_i=1\)。
对于 \(100\%\) 的数据 \(1 \leq l\leq r\leq n\leq 1 \times 10^{5}\ ,\ 1\leq m\leq 1 \times 10^{5}\ ,\ |s|\ ,\ |k|\ ,\ |a_i| \leq 1 \times 10^{9}\)。
特别提示
2.解法
先完成以上两题,这道题也就很简单了。(这两道题是开启这道题的钥匙。)
我们可以推一下式子,比如现在我们对1到N加上一个等差数列后的总和。
\(\sum_{i=1}^n (a_i+s+(i-1)\times k)^{2}\)
\(\Longleftrightarrow \sum_{i=1}^{n} a_i^{2}+(s+(i-1)\times k)^{2}+2\times a_i \times (s+(i-1)\times 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+2s\sum_{i=1}^{n}a_i+2k\sum_{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\n",(Qurey(1,1,N,X,Y)+Mod)%Mod);
}
return 0;
}