Loading

QwQcOrZ 的数据结构题 VI

题意:

给出一个序列,支持区间加等差数列,区间查询平方和。

需要计算的是

\[\sum\limits_{i=l}^r(a_i(s+(i-l)k)+(s+(i-l)k)^2) \]

发现后一部分为等差数列平方和

\[\begin{aligned} \sum\limits_{i=1}^n(s+(i-1)k)^2 &= s^2+(s+k)^2+(s+2k)^2+\cdots+(s+(n-1)k)^2 \\ & = s^2+s^2+2sk+k^2+s^2+4sk+4k^2+\cdots+s^2+2(n-1)sk+(n-1)^2k^2 \\ & = ns^2+\sum\limits_{i=2}^n(2isk)+\frac{n(n-1)(2n-1)}{6}k^2(k^2\sum_{i=1}^{n-1}i^2 ) \\ \end{aligned} \]

考虑如何计算

\[\sum\limits_{i=l}^r(a_i(s+(i-l)k)) \]

将式子拆开得到

\[\sum\limits_{i=l}^r(a_i(s+(i-l)k))=\sum\limits_{i=l}^r a_is+\sum\limits_{i=l}^r(a_i(i-l)k) \]

\[\sum\limits_{i=l}^r(a_i(i-l)k)=k(\sum\limits_{i=l}^r(a_i i)-l\sum\limits_{i=l}^r a_i) \]

那么可以在线段树上维护

\(sum=\sum_{i=l}^r a_i,sum'=\sum_{i=l}^r(a_i(i-l+1)),pow=\sum_{i=l}^r a_i^2\)

考虑如何修改 \(sum'\)

\(sum'=sum+\sum_{i=l}^r((s+(i-l)k)(i-l))=\frac{len(len-1)}{2}s+(\frac{len(len-1)(2len-1)}{6}-\frac{len(len-1)}{2})k\)

简单来说就是求\(\sum_{i=l}^r (a_i+(s+(i-l)k))^2\)

可以拆成\(\sum_{i=l}^r a_i^2+2\sum_{i=l}^r(a_i(s+(i-l)k))+\sum_{i=l}^r(s+(i-l)k)^2\)

具体计算方法上面有写。

然后就是考虑如何搞区间平方和,假设这里为加上一个数\(x\)

\(\sum_{i=l}^r=(a_i+x)^2=(a_l^2+a_{l+1}^2+\cdots+a_{r-1}^2+a_r^2+2x(a_l+a_{l+1}+\cdots+a_{r-1}+a_r)+(r-l+1)x^2)\)

所以说区间修改的时候加上\(2x\sum_{i=l}^r+(r-l+1)x^2\)即可。

维护的时候只要一个数组维护区间和,一个维护区间加的懒标记,一个维护区间平方和即可。

稍微推一下:\(sum=(a_l+s)^2+(a_{l+1}+(s+k))^2+\cdots+(a_r+(s+(r-l)k))^2\)

拆开得到:

\[a_l^2+a_{l+1}^2+\cdots +a_r^2+2a_l s+2a_{l+1}(s+k)+\cdots+2a_r(s+(r-l)k)+s^2+(s+k)^2+\cdots+(s+(r-l)k)^2 \]

仍然是拆成三部分搞\(\sum_{i=l}^r a_i^2,2(s\sum_{i=l}^r a_i+k\sum_{i=l}^ra_i (i-l)),ns^2+(r-l+1)(r-l)sk+\frac{(r-l)(r-l+1)(2r-2l+1)}{6}k^2\)

这些显然都是已经维护了的东西。

#include<bits/stdc++.h>
#define ld long double
#define tset puts("qwq");
#define test puts("QAQ");
#define pb(a) push_back(a)
#define pii pair<int,int> 
#define mkp make_pair
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define int long long
#define R(i,a,b) for(int i=(a),i##E=(b);i<=i##E;i++)
#define L(i,a,b) for(int i=(b),i##E=(a);i>=i##E;i--)
#define clr(f,n) memset(f,0,sizeof(int)*(n))
#define cpy(f,g,n) memcpy(f,g,sizeof(int)*(n))
#define Swap(x,y) (x^=y^=x^=y)
template <typename T> bool ckmax(T &x, T y) { return x<y?x=y,true:false;}
template <typename T> bool ckmin(T &x, T y) { return x>y?x=y,true:false;}
using namespace std;
//const ll inf=0x7f7f7f7f7f7f7f3f;
const ll inf=(1ll<<60);
//const int inf=0x7f7f7f7f;
//const int mod=1e9+7;
const double Pi=acos(-1);
const int mod=1e9+7;
const double eps=1e-6;
inline int fpow(int a,int b=mod-2,int p=mod){int res=1;a%=mod;while(b){if(b&1)res=res*a%p;a=a*a%p;b>>=1;}return res;}
inline ll read()
{
    char c=getchar();ll x=0;bool f=0;
    for(;!isdigit(c);c=getchar())f^=!(c^45);
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    if(f)x=-x;
    return x;
}
inline void write(ll x){if (x<0){putchar('-');write(-x);return;}if (x>=10) write(x/10);putchar(x%10+'0');}
inline void writesp(ll x){write(x),putchar(' ');}
inline void writeln(ll x){write(x);putchar('\n');}
/*
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
mt19937 rand_num(seed);  
uniform_int_distribution<long long> dist(0, 10000000);  // ¸ø¶¨·¶Î§
printf("%lld ",dist(rand_num));
*/
const int N=2e5+10;
const int inv2=500000004;
const int inv6=166666668;
int a[N],n,m;
int l_n[N<<2];
int sm[N<<2],s_m[N<<2],sqr[N<<2];
int lak[N<<2],las[N<<2];
int sf1[N],sf2[N];//
inline int get_SUM(int s,int k,int len) {return (len*s*s%mod+2*sf1[len-1]*k%mod*s%mod+sf2[len-1]*k*k%mod)%mod;}
void push_up(int x)
{
	sm[x]=(sm[x<<1]+sm[x<<1|1])%mod;
	sqr[x]=(sqr[x<<1]+sqr[x<<1|1])%mod;
	s_m[x]=(s_m[x<<1]+l_n[x<<1]*sm[x<<1|1]%mod+s_m[x<<1|1])%mod;
}
void upd(int s,int k,int x)
{
	sqr[x]=(sqr[x]+(s*sm[x]+(s_m[x]-sm[x]+mod)%mod*k)%mod*2%mod+l_n[x]*s%mod*s%mod+(l_n[x]-1)*s%mod*k%mod+(l_n[x]-1)*(l_n[x]-1)%mod*s%mod*k%mod+sf2[l_n[x]-1]*k%mod*k%mod)%mod;
	sm[x]=(sm[x]+(s*2+(l_n[x]-1)*k%mod)*l_n[x]%mod*inv2)%mod;
	s_m[x]=(s_m[x]+s*sf1[l_n[x]]%mod+(sf2[l_n[x]]-sf1[l_n[x]]+mod)%mod*k%mod)%mod;
	lak[x]=(lak[x]+k)%mod;
	las[x]=(las[x]+s)%mod;
}
void push_down(int x)
{
	if(las[x]||lak[x])
	{
		upd(las[x],lak[x],x<<1);
		las[x]=(las[x]+l_n[x<<1]*lak[x])%mod;
		upd(las[x],lak[x],x<<1|1);
		las[x]=lak[x]=0;
	}
}
void build(int l,int r,int x)
{
	l_n[x]=r-l+1;
	if(l==r) 
	{
		sm[x]=a[l];
		s_m[x]=a[l];
		sqr[x]=a[l]*a[l]%mod;
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,x<<1);
	build(mid+1,r,x<<1|1);
	push_up(x);
}
void modify(int L,int R,int l,int r,int x,int s,int k)
{
	if(L<=l&&r<=R)
	{
		upd(((s+(l-L)*k)%mod+mod)%mod,(k%mod+mod)%mod,x);
		return;
	}
	push_down(x);
	int mid=(l+r)>>1;
	if(L<=mid) modify(L,R,l,mid,x<<1,s,k);
	if(mid<R) modify(L,R,mid+1,r,x<<1|1,s,k);
	push_up(x);
}	
int query(int L,int R,int l,int r,int x)
{
	if(L<=l&&r<=R) return sqr[x];
	push_down(x);
	int mid=(l+r)>>1,ret=0;
	if(L<=mid) ret=(ret+(query(L,R,l,mid,x<<1)%mod+mod)%mod)%mod;
	if(mid<R) ret=(ret+(query(L,R,mid+1,r,x<<1|1)%mod+mod)%mod)%mod;
	ret%=mod,ret+=mod,ret%=mod;
	return ret;
}
signed main()
{
	freopen("T4.in","r",stdin);
	freopen("T4.out","w",stdout);
	n=read(),m=read();
	R(i,1,n) sf1[i]=(sf1[i-1]+i)%mod,sf2[i]=(sf2[i-1]+1ll*i*i)%mod;
	R(i,1,n) a[i]=(read()%mod+mod)%mod;
	int opt,l,r,k,s;
	build(1,n,1);
	while(m--)
	{
		opt=read(),l=read(),r=read();
		if(!opt) s=read(),k=read(),modify(l,r,1,n,1,s,k);	
		else writeln(query(l,r,1,n,1));
	}
}
posted @ 2022-01-07 17:47  yoisaki_hizeci  阅读(132)  评论(0)    收藏  举报