相连的宇宙 题解

大家好,今天来一道线段树的题目。

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}\)

特别提示

\[\sum_{i=1}^n i^{2} = \dfrac{n(n+1)(2n+1)}{6} \]

2.解法

洛谷 P1471 方差+洛谷 P1438 无聊的数列

先完成以上两题,这道题也就很简单了。(这两道题是开启这道题的钥匙。)

我们可以推一下式子,比如现在我们对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;
}
posted @ 2020-05-18 18:36  eromangasensei  阅读(178)  评论(0编辑  收藏  举报