zoukankan      html  css  js  c++  java
  • 洛谷 1471 方差

    【题解】

      1,本题要求维护一个序列,支持区间加k,询问区间平均数和方差。

      2,询问平均数显然很好处理,在线段树上维护区间和sum以及区间长度len即可。

      3,方差的处理就相对麻烦一些。需要研究一下公式。

      我们先看看方差的公式:

      

      那就是1/n乘上这个式子:

      也就是区间平方和Sqr-区间和Sum的两倍+平均数Ave的平方乘区间长Len,所得结果再除以区间长Len

      那么我们在线段树上再维护一个区间平方和Sqr就好了

      4,在区间修改的时候,怎么维护Sqr呢?我们可以发现修改后的平方和为:

      (k是区间加上的数)

      展开式子就是:

      

      那就是原来的Sqr+原来的Sum乘k乘2+k的平方乘区间长Len

      这样,我们就可以解决这个问题了

    #include<cstdio>
    #include<algorithm>
    #define N (800010)
    #define ls (u<<1)
    #define rs (u<<1|1)
    #define mid ((a[u].l+a[u].r)>>1)
    #define len(x) (a[x].r-a[x].l+1)
    using namespace std;
    int n,m,opt,x,y;
    double del,sqr,sum;
    struct tree{
    	int l,r;
    	double del,sum,sqr;
    }a[N];
    inline int read(){
    	int k=0,f=1; char c=getchar();
    	while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    	while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    	return k*f;
    }
    inline void pushup(int u){
    	a[u].sum=a[ls].sum+a[rs].sum;
    	a[u].sqr=a[ls].sqr+a[rs].sqr;
    }
    inline void pushdown(int u){
    	if(!a[u].del) return; double D=a[u].del; a[u].del=0;
    	a[ls].del+=D; a[ls].sqr+=a[ls].sum*D*2+D*D*len(ls); a[ls].sum+=len(ls)*D;
    	a[rs].del+=D; a[rs].sqr+=a[rs].sum*D*2+D*D*len(rs); a[rs].sum+=len(rs)*D;
    }
    void build(int u,int l,int r){
    	a[u].l=l; a[u].r=r;
    	if(l<r) build(ls,l,mid),build(rs,mid+1,r),pushup(u);
    	else scanf("%lf",&a[u].sum),a[u].sqr=a[u].sum*a[u].sum;
    }
    void update(int u,int l,int r,double del){
    	if(l<=a[u].l&&a[u].r<=r){
    		a[u].sqr+=a[u].sum*del*2+del*del*len(u);
    		a[u].sum+=len(u)*del;
    		a[u].del+=del;
    		return;
    	}
    	pushdown(u);
    	if(l<=mid) update(ls,l,r,del);
    	if(r>mid) update(rs,l,r,del);
    	pushup(u);
    }
    void query(int u,int l,int r,double &sqr,double &sum){
    	if(l<=a[u].l&&a[u].r<=r){
    		sqr+=a[u].sqr; sum+=a[u].sum;
    		return;
    	}
    	pushdown(u);
    	if(l<=mid) query(ls,l,r,sqr,sum);
    	if(r>mid) query(rs,l,r,sqr,sum);
    }
    int main(){
    	n=read(); m=read();
    	build(1,1,n);
    	while(m--){
    		if((opt=read())==1) x=read(),y=read(),scanf("%lf",&del),update(1,x,y,del);
    		if(opt==2){
    			sum=0; sqr=0;
    			x=read(); y=read();
    			query(1,x,y,sqr,sum);
    			printf("%.4lf
    ",1.0*sum/(y-x+1));
    		}
    		if(opt==3){
    			sum=0; sqr=0;
    			x=read(); y=read(); int l=y-x+1;
    			query(1,x,y,sqr,sum);
    			double ave=1.0*sum/l;
    			//printf("sqr=%.4f sum=%.4f
    ",sqr,sum);
    			printf("%.4lf
    ",(sqr-2*sum*ave+l*ave*ave)/l);
    		}
    	}
    	return 0;
    }
    

      

      

  • 相关阅读:
    webservice调用三种方式
    webservice访问权限控制利用TOMCAT用户
    ubuntu添加ppa源
    win7与ubuntu共享文件夹
    Cinema 4D* 中令人惊叹的体积效果
    线程并行化的概念及其用法
    什么是代码现代化?
    英特尔® 软件开发人员十大故事 | 五月
    英特尔® 实感™ 前置摄像头 SR300 和 F200 的比较
    面向英特尔® x86 平台的 Unity* 优化指南: 第 1 部分
  • 原文地址:https://www.cnblogs.com/DriverLao/p/8390861.html
Copyright © 2011-2022 走看看