zoukankan      html  css  js  c++  java
  • 相连的宇宙 题解

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

    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;
    }
    
  • 相关阅读:
    面试问烂的 MySQL 四种隔离级别,看完吊打面试官!
    注解Annotation实现原理与自定义注解例子
    趣图:苦逼的后端工程师
    session深入探讨
    趣图:听说996工作可以获得巨大成长
    面试官:一个 TCP 连接可以发多少个 HTTP 请求?
    聊聊前后端分离接口规范
    趣图:什么?需求文档又改了
    ASP.NET页面中去除VIEWSTATE视
    C#
  • 原文地址:https://www.cnblogs.com/eromangasensei/p/12912327.html
Copyright © 2011-2022 走看看