QwQcOrZ 的数据结构题 VI
题意:
给出一个序列,支持区间加等差数列,区间查询平方和。
需要计算的是
发现后一部分为等差数列平方和
考虑如何计算
将式子拆开得到
而
那么可以在线段树上维护
\(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\)
拆开得到:
仍然是拆成三部分搞\(\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));
	}
}

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号