我是靠谱客的博主 粗犷心锁,最近开发中收集的这篇文章主要介绍【洛谷P5142】区间方差,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目

题目背景
出题人并没有能力写有趣的题面……

题目描述
对于一个长度为 nn 的序列 a_1,a_2,a_3cdots a_na
1

,a
2

,a
3

⋯a
n

,我们定义它的平均数 aa 为:

a=frac{1}{n}sum_{i=1}^{n}a_i
a=
n
1

i=1

n

a
i

并定义它的方差 dd 为:

d=frac{1}{n}sum_{i=1}{n}(a_i-a)2
d=
n
1

i=1

n

(a
i

−a)
2

现在给定一个长度为 nn 的序列 b_1,b_2cdots b_nb
1

,b
2

⋯b
n

。你需要支持两种操作。每种操作的格式为 c x y。

若 c=1c=1,为修改操作,代表将 b_xb
x

赋值为 yy。

若 c=2c=2,为查询操作,代表查询 b_xb
x

到 b_yb
y

的方差。

为了避免浮点数误差,请以分数取模形式输出结果(对 1000000007(10^9+710
9
+7)取模)。

输入格式
第一行两个整数 n,mn,m,代表序列 bb 的长度为 nn,有 mm 个操作。

第二行 nn 个整数 b_ib
i

,表示序列 bb 的初始值。

下面有 mm 行整数,每行格式为 c a b,含义如上文所示。保证所有操作合法。

输出格式
对于每个操作 2,输出一行。

输入输出样例
输入 #1复制
4 8
0 0 0 0
1 1 1
1 2 2
1 3 3
1 4 4
2 1 1
2 1 2
2 1 3
2 1 4
输出 #1复制
0
250000002
666666672
250000003
说明/提示
样例 1 解释
四次修改后,序列 bb 为:{1,2,3,4}{1,2,3,4}。

区间 [1,1][1,1] 的方差为 00。

区间 [1,2][1,2] 的方差为 frac{1}{4}
4
1

。44 的逆元为 250000002250000002。

区间 [1,3][1,3] 的方差为 frac{2}{3}
3
2

。33 的逆元为 333333336333333336,2times333333336bmod M=6666666722×333333336modM=666666672。

数据规模与约定
对于 50%50% 的数据,nleq 1000n≤1000,mleq 1000m≤1000。
对于 100%100% 的数据,1leq n,mleq 1times 10^51≤n,m≤1×10
5
,1leq b_ileq 1times 10^91≤b
i

≤1×10
9
,1leq xleq n1≤x≤n。对于操作 1,1leq yleq 1times 10^91≤y≤1×10
9
。对于操作2,xleq yleq nx≤y≤n。

思路

将方差公式化简,有
n d = ∑ i = 1 n ( b i − b ‾ ) 2 = ∑ i = 1 n ( b i 2 − 2 b i b ‾ + b ‾ 2 ) = ∑ i = 1 n b i 2 − 2 n b ‾ ∑ i = 1 n b i + n b ‾ 2 nd=sum_{i=1}^n (b_i-overline{b})^2 =sum_{i=1}^n (b_i^2-2b_ioverline{b}+overline{b}^2)=sum_{i=1}^nb_i^2-2noverline{b}sum_{i=1}^nb_i+n overline{b}^2 nd=i=1n(bib)2=i=1n(bi22bib+b2)=i=1nbi22nbi=1nbi+nb2
b ‾ = ∑ i = 1 n b i n overline{b}=frac{sum_{i=1}^n b_i}{n} b=ni=1nbi

n d = ∑ i = 1 n b i 2 − 2 ( ∑ i = 1 n b i ) 2 + ( ∑ i = 1 n b i ) 2 n nd=sum_{i=1}^n b_i^2-2{(sum_{i=1}^n b_i)}^2+frac{{(sum_{i=1}^n b_i)}^2}{n} nd=i=1nbi22(i=1nbi)2+n(i=1nbi)2
所以 n 2 d = n ∑ i = 1 n b i 2 − 2 n ( ∑ i = 1 n b i ) 2 + ( ∑ i = 1 n b i ) 2 n^2 d=nsum_{i=1}^n b_i^2-2n{(sum_{i=1}^n b_i)}^2+{(sum_{i=1}^n b_i)}^2 n2d=ni=1nbi22n(i=1nbi)2+(i=1nbi)2
维护区间和以及区间平方和即可

代码

#include<btis/stdc++.h>
using namespace std;

typedef long long ll;
const ll p = 1e9+7;
const ll maxn = 1e5+3;
ll a[maxn],sumv1[maxn<<4],sumv2[maxn<<4],in[maxn],n,m;

inline void pushup(ll o)
{
	sumv1[o] = (sumv1[o<<1]+sumv1[o<<1|1])%p;
	sumv2[o] = (sumv2[o<<1]+sumv2[o<<1|1])%p;
}

inline void build(ll o,ll l,ll r)
{
	if(l==r)
	{
		sumv1[o] = a[l]%p;
		sumv2[o] = a[l]*a[l]%p;
		return ;
	}
	ll mid = (l+r)>>1;
	build(o<<1,l,mid);
	build(o<<1|1,mid+1,r);
	pushup(o);
}

void change(ll o,ll l, ll r,ll q,ll v)
{
	if(l==r)
	{
		sumv1[o] = v%p;
		sumv2[o] = v*v%p;
		return ;
	}
	ll mid = (l+r)>>1;
	if(q<=mid)
		change(o<<1,l,mid,q,v);
	else
		change(o<<1|1,mid+1,r,q,v);
	pushup(o);
}

ll query1(ll o,ll l,ll r,ll ql,ll qr)
{
	if(ql<=l&&r<=qr)
		return sumv1[o]%p;
	ll ans = 0;
	ll mid = (l+r)>>1;
	if(ql<=mid)
		ans += query1(o<<1,l,mid,ql,qr)%p;
	if(qr>mid)
		ans += query1(o<<1|1,mid+1,r,ql,qr)%p;
	return ans%p;
}

//区间平方和
ll query2(ll o,ll l,ll r,ll ql,ll qr)
{
	if(ql<=l&&r<=qr)
		return sumv2[o]%p;
	ll ans = 0;
	ll mid = (l+r)>>1;
	if(ql<=mid)
		ans += query2(o<<1,l,mid,ql,qr)%p;
	if(qr>mid)
		ans += query2(o<<1|1,mid+1,r,ql,qr)%p;
	return ans%p;
}

int main()
{
	scanf("%lld%lld",&n,&m);
	in[1] = 1;
	for(int i = 2;i<=n;++i)
		in[i] = (ll)(p-p/i)*in[p%i]%p;

	for(int i = 1;i<=n;++i)
		scanf("%lld",&a[i]);
	build(1,1,n);
	while(m--)
	{
		ll opt,l,r;
		scanf("%lld%lld%lld",&opt,&l,&r);
		if(opt == 1)
			change(1,1,n,l,r%p);
		else
		{
			ll s1 = query1(1,1,n,l,r)%p,s2 = query2(1,1,n,l,r)%p,inv = in[r-l+1],tot1 = s1*inv%p,tot2 = s2*inv%p-tot1*tot1%p;	
			tot2 = (tot2%p+p)%p;   
			printf("%lldn",tot2);
		}   
	}
	return 0;
}

最后

以上就是粗犷心锁为你收集整理的【洛谷P5142】区间方差的全部内容,希望文章能够帮你解决【洛谷P5142】区间方差所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部