【五校联考4day1】寻找神格

这题t<=2的都可以很容易地更改或是查询,重点就是求方差了。
在这里插入图片描述
题目已经给了方差的求法,我们只需要将其化简即可。(手推就行了)
最后化简成:

A和B之间的:

sum(a[i]^2)/(B-A+1)-sum(a[i])*sum(a[i])/(B-A+1)/(B-A+1)

sum指的是A到B的区间和(a[i]^2为平方和,a[i]为和)

最后构造两个线段树,一个存平方和,一个存和即可。在线的
上标:

#include<cstdio>
#include<algorithm>
#define db double
#define ll long long 
using namespace std;
int n,q,tt,A,B,C;
ll lazy[600010],t[600010],tf[600010];
db ans=0;

void update(int x,int l,int r)
{
	if (!lazy[x]) return;
	tf[x]+=(ll)2*t[x]*lazy[x]+(ll)(r-l+1)*lazy[x]*lazy[x];
	t[x]+=(ll)(r-l+1)*lazy[x];
	if (l<r) lazy[x<<1]+=lazy[x],lazy[x<<1|1]+=lazy[x];
	lazy[x]=0;
}

void inser(int x,int l,int r,int fl,int fr,int ins)
{
	update(x,l,r);
	if (l==fl && r==fr) {lazy[x]+=ins,update(x,l,r); return;}
	int mid=l+r>>1;
	if (fr<=mid) inser(x<<1,l,mid,fl,fr,ins);
	else if (fl>mid) inser(x<<1|1,mid+1,r,fl,fr,ins);
	else inser(x<<1,l,mid,fl,mid,ins),inser(x<<1|1,mid+1,r,mid+1,fr,ins);
	update(x<<1,l,mid),update(x<<1|1,mid+1,r);
	t[x]=t[x<<1]+t[x<<1|1];
	tf[x]=tf[x<<1]+tf[x<<1|1];
}

ll gsum(int x,int l,int r,int fl,int fr)
{
	update(x,l,r);
	if (l==fl && r==fr) return t[x];
	int mid=l+r>>1;
	if (fr<=mid) return gsum(x<<1,l,mid,fl,fr);
	else if (fl>mid) return gsum(x<<1|1,mid+1,r,fl,fr);
	else return gsum(x<<1,l,mid,fl,mid)+gsum(x<<1|1,mid+1,r,mid+1,fr);
}

ll gfs(int x,int l,int r,int fl,int fr)
{
	update(x,l,r);
	if (l==fl && r==fr) return tf[x];
	int mid=l+r>>1;
	if (fr<=mid) return gfs(x<<1,l,mid,fl,fr);
	else if (fl>mid) return gfs(x<<1|1,mid+1,r,fl,fr);
	else return gfs(x<<1,l,mid,fl,mid)+gfs(x<<1|1,mid+1,r,mid+1,fr);
}

int main()
{
	freopen("sg.in","r",stdin);
	freopen("sg.out","w",stdout);
//	方差=sum(a[i]^2)/n-sum(a[i])^2/n^2

	scanf("%d%d\n",&n,&q);
	for (int i=1,x;i<=n;i++)
		scanf("%d",&x),inser(1,1,n,i,i,x);
	while (q--)
	{
		scanf("%d",&tt);
		if (tt==0)
		{
			scanf("%d%d",&A,&B);
			inser(1,1,n,A,A,B);
		}
		else if (tt==1)
		{
			scanf("%d%d%d",&A,&B,&C);
			inser(1,1,n,A,B,C);
		}	
		else if (tt==2)
		{
			scanf("%d%d",&A,&B);
			printf("%lld\n",gsum(1,1,n,A,B));
		}
		else if (tt==3)
		{
			scanf("%d%d",&A,&B);
			ans=gsum(1,1,n,A,B);
			ans=(db)gfs(1,1,n,A,B)/(B-A+1)-ans*ans/(B-A+1)/(B-A+1);
			printf("%.10lf\n",ans);
		}
	}
	return 0;
}
posted @ 2019-01-20 14:53  jz929  阅读(124)  评论(0编辑  收藏  举报