LGP5142题解

题意简明,不说了(

因为教练让同学们做线段树的题,早就会了线段树的我就来爆踩水水蓝了/kk

首先推一下柿子:

\[\frac 1 n\sum_{i=1}^n(a_i^2-2 \times a_i \times \overline a + \overline a^2) \]

\[\frac 1 n(\sum_{i=1}^na_i^2-2\overline a \times \sum_{i=1}^na_i + n \times \overline a^2) \]

于是用线段树维护一下区间和&区间平方和就好了。。。

愿意的话甚至可以用树状数组维护。。。

code:

#include<cstdio>
const int M=1e5+5,mod=1e9+7;
int n,m,a[M];
inline int Inv(int a){
	int b=mod-2,ans=1;
	for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;
	return ans;
}
inline int Add(const int&a,const int&b){
	return a+b>=mod?a+b-mod:a+b;
}
inline int Del(const int&a,const int&b){
	return a-b<0?a-b+mod:a-b;
}
struct Node{
	int sum,squ;
	inline Node operator+(const Node&it)const{
		return (Node){Add(sum,it.sum),Add(squ,it.squ)};
	}
}tmp,t[M<<2];
inline void update(const int&u){
	t[u]=t[u<<1]+t[u<<1|1];
}
void build(int u,int l,int r){
	if(l==r)t[u].sum=a[l],t[u].squ=1ll*a[l]*a[l]%mod;
	else{
		int mid=l+r>>1;
		build(u<<1,l,mid);build(u<<1|1,mid+1,r);
		update(u);
	}
}
void Modify(int u,int x,int val,int l=1,int r=n){
	if(l==r)t[u].sum=val,t[u].squ=1ll*val*val%mod;
	else{
		int mid=l+r>>1;
		if(x<=mid)Modify(u<<1,x,val,l,mid);
		else Modify(u<<1|1,x,val,mid+1,r);
		update(u);
	}
}
Node Query(int u,int L,int R,int l=1,int r=n){
	if(L>r||l>R)return (Node){0,0};
	if(L<=l&&r<=R)return t[u];
	int mid=l+r>>1;
	return Query(u<<1,L,R,l,mid)+Query(u<<1|1,L,R,mid+1,r);
}
signed main(){
	register int i,f,L,R,val,inv;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;++i)scanf("%d",a+i);
	build(1,1,n);
	for(i=1;i<=m;++i){
		scanf("%d%d%d",&f,&L,&R);
		if(f==1){
			Modify(1,L,R);
		}
		else{
			tmp=Query(1,L,R);
			inv=Inv(R-L+1);
			val=1ll*inv*tmp.sum%mod;
			printf("%d\n",1ll*inv*Del(Add(tmp.squ,1ll*val*val%mod*(R-L+1)%mod),2ll*val*tmp.sum%mod)%mod);
		}
	}
}
posted @ 2022-01-10 15:47  Prean  阅读(25)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};