相连的宇宙 题解

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

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

特别提示

[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) 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;
}
原文地址:https://www.cnblogs.com/eromangasensei/p/12912327.html