ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P1471 方差

2022-08-30 14:00:30  阅读:147  来源: 互联网

标签:P1471 qr return 方差 int double nd ql


给定数列,维护区间平均数和区间方差,并支持区间修改。\(n\leq10^5,m\leq10^5\)。


线段树维护平均数比较简单,重点在于如何维护方差。

具体公式参考了这篇题解,就不详细展开,推出来以后就变成简单的线段树维护问题。

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

struct node{
	double sum,tag,pow_sum;
	int l,r;
};

struct ST{
	node nd[400005];
	double a[400005];
	inline int ls(int p){
		return p<<1;
	}
	inline int rs(int p){
		return p<<1|1;
	}
	inline void push_up(int p){
		nd[p].sum=nd[ls(p)].sum+nd[rs(p)].sum;
		nd[p].pow_sum=nd[ls(p)].pow_sum+nd[rs(p)].pow_sum;
		return;
	}
	inline void add_tag(int p,double k){
		int l=nd[p].l;
		int r=nd[p].r;
		nd[p].tag+=k;
		nd[p].pow_sum+=2*k*(nd[p].sum)+(r-l+1)*k*k;
		nd[p].sum+=k*(double)(r-l+1);
		return;
	}
	void push_down(int p){
		add_tag(ls(p),nd[p].tag);
		add_tag(rs(p),nd[p].tag);
		nd[p].tag=0.0;
		return;
	}
	void build(int l,int r,int p){
		nd[p].l=l;
		nd[p].r=r;
		if(l==r){
			nd[p].sum=a[l];
			nd[p].pow_sum=a[l]*a[l];
			return;
		}
		int mid=(l+r)>>1;
		build(l,mid,ls(p));
		build(mid+1,r,rs(p));
		push_up(p);
		return;
	}
	void updata(int p,int ql,int qr,double k){
		int l=nd[p].l;
		int r=nd[p].r;
		if(ql<=l && r<=qr){
			add_tag(p,k);
			return;
		}
		push_down(p);
		int mid=(l+r)>>1;
		if(ql<=mid)
			updata(ls(p),ql,qr,k);
		if(qr>mid)
			updata(rs(p),ql,qr,k);
		push_up(p);
		return;
	}
	double get_1(int p,int ql,int qr){
		int l=nd[p].l;
		int r=nd[p].r;
		if(ql<=l && r<=qr){
			return nd[p].sum;
		}
		push_down(p);
		int mid=(l+r)>>1;
		double ret=0.0;
		if(ql<=mid)
			ret+=get_1(ls(p),ql,qr);
		if(qr>mid)
			ret+=get_1(rs(p),ql,qr);
		return ret;
	}
	double get_2(int p,int ql,int qr){
		int l=nd[p].l;
		int r=nd[p].r;
		if(ql<=l && r<=qr){
			return nd[p].pow_sum;
		}
		push_down(p);
		int mid=(l+r)>>1;
		double ret=0.0;
		if(ql<=mid)
			ret+=get_2(ls(p),ql,qr);
		if(qr>mid)
			ret+=get_2(rs(p),ql,qr);
		return ret;
	}
	double query_1(int ql,int qr){
		return get_1(1,ql,qr)/(double)(qr-ql+1);
	}
	double query_2(int ql,int qr){
		double q1=query_1(ql,qr);
		return get_2(1,ql,qr)/(qr-ql+1)-q1*q1;
	}
}S;

int n,m;
int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;++i)
		scanf("%lf",&S.a[i]);
	S.build(1,n,1);
	while(m){
		m--;
		int op,x,y;
		scanf("%d %d %d",&op,&x,&y);
		switch(op){
			case 1:{
				double k;
				scanf("%lf",&k);
				S.updata(1,x,y,k);
				break;
			}
			case 2:{
				printf("%.4lf\n",S.query_1(x,y));
				break;
			}
			case 3:{
				printf("%.4lf\n",S.query_2(x,y));
				break;
			}
		}
	}
	return 0;
}

标签:P1471,qr,return,方差,int,double,nd,ql
来源: https://www.cnblogs.com/zhouzizhe/p/16639066.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有