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

    蒟蒻HansBug在一本数学书里面发现了一个神奇的数列,包含N个实数。他想算算这个数列的平均数和方差。

                 ——by 洛谷;

    http://www.luogu.org/problem/show?pid=1471



      平均数可以用线段树,维护区间和,直接维护平均数也行;

        然后对于方差;她有个公式的:

        S=[(a-Z)²+(b-Z)²+(c-Z)²+(d-Z)²+(e-Z)²...]/n(Z为平均数)

        S=[区间平方和-2*n*平均数²+n*平均数²]/n;

        S=[区间平方和-n*平均数²]/n;

        所以维护个平方和就好了;

        然后,平方和怎么区间加呢?

        她也有个公式:

        (a+z)²+(b+z)²+(c+z)²+(d+z)²+(e+z)²(你把她拆开嘛。。)

       =以前平方和+(2z*(Z*n)+n*z²);

    然后是代码解释,

    我只打了一个Lazy,意为在该区间的子树上要区间加,然后两个线段树共用;

    因为平方和修改要用区间平均数未修改的值,故两树同步修改,先改平方和;

    代码如下:

      1 #include<cstdio>
      2 #include<iostream>
      3 using namespace std;
      4 double treen[1000001];
      5 double treen1[1000001];
      6 double lz[1000001];
      7 int n,m,R,L;
      8 double a;
      9 
     10 void build(int ,int ,int );
     11 void add(int ,int ,int );
     12 double sum( int ,int ,int );
     13 double sum1(int ,int ,int );
     14 void down(int ,int ,int );
     15 
     16 int main()
     17 {
     18     int i,j,b;
     19     double ans,k;
     20     scanf("%d%d",&n,&m);
     21     build(1,n,1);
     22     for(i=1;i<=m;i++)
     23     {
     24         scanf("%d",&b);
     25         if(b==1)
     26         {
     27             scanf("%d%d",&L,&R);
     28             cin>>a;
     29             add(1,n,1);
     30         }
     31         if(b==2)
     32         {
     33             scanf("%d%d",&L,&R);
     34             ans=sum(1,n,1)/(R-L+1);
     35             printf("%.4lf
    ",ans);
     36         }
     37         if(b==3)
     38         {
     39             scanf("%d%d",&L,&R);
     40             ans=sum(1,n,1)/(R-L+1);
     41             ans=ans*ans;
     42             k=sum1(1,n,1);
     43             ans=k/(R-L+1)-ans;
     44             printf("%.4lf
    ",ans);
     45         }
     46     }
     47 }
     48 
     49 void build(int l,int r,int nu)
     50 {
     51     if(l==r)
     52     {
     53         scanf("%lf",&treen[nu]);
     54         treen1[nu]=treen[nu]*treen[nu];
     55         return ;
     56     }
     57     int mid=(l+r)>>1;
     58     build(l,mid,nu<<1);
     59     build(mid+1,r,(nu<<1)+1);
     60     treen[nu]=(treen[nu<<1]*(mid-l+1)+treen[(nu<<1)+1]*(r-mid))/(r-l+1.0);
     61     treen1[nu]=treen1[nu<<1]+treen1[(nu<<1)+1];
     62 }
     63 
     64 void add(int l,int r,int nu)
     65 {
     66     if(L<=l&&r<=R)
     67     {
     68         lz[nu]+=a;
     69         treen1[nu]+=(r-l+1)*(a*2*treen[nu]+a*a);
     70         treen[nu]+=a;
     71         return ;
     72     }
     73     int mid=(l+r)>>1;
     74     down(l,r,nu);
     75     if(L<=mid)
     76         add(l,mid,nu<<1);
     77     if(R>=mid+1)
     78         add(mid+1,r,(nu<<1)+1);
     79     treen[nu]=(treen[nu<<1]*(mid-l+1)+treen[(nu<<1)+1]*(r-mid))/(r-l+1.0);
     80     treen1[nu]=treen1[nu<<1]+treen1[(nu<<1)+1];
     81 }
     82 
     83 double sum(int l,int r,int nu)
     84 {
     85     double su=0;
     86     if(L<=l&&r<=R)
     87     {
     88         return treen[nu]*(r-l+1);
     89     }
     90     int mid=(l+r)>>1;
     91     down(l,r,nu);
     92     if(L<=mid)
     93         su+=sum(l,mid,nu<<1);
     94     if(R>=mid+1)
     95         su+=sum(mid+1,r,(nu<<1)+1);
     96     return su;
     97 }
     98 
     99 double sum1(int l,int r,int nu)
    100 {
    101     double su=0;
    102     if(L<=l&&r<=R)
    103     {
    104         return treen1[nu];
    105     }
    106     int mid=(l+r)>>1;
    107     down(l,r,nu);
    108     if(L<=mid)
    109         su+=sum1(l,mid,nu<<1);
    110     if(R>=mid+1)
    111         su+=sum1(mid+1,r,(nu<<1)+1);
    112     return su;
    113 }
    114 
    115 void down(int l,int r,int nu)
    116 {
    117     int mid=(l+r)>>1;
    118     lz[nu<<1]+=lz[nu];
    119     lz[(nu<<1)+1]+=lz[nu];
    120     treen1[nu<<1]+=(mid-l+1)*(2*treen[nu<<1]*lz[nu]+lz[nu]*lz[nu]);
    121     treen1[(nu<<1)+1]+=(r-mid)*(2*treen[(nu<<1)+1]*lz[nu]+lz[nu]*lz[nu]);
    122     treen[nu<<1]+=lz[nu];
    123     treen[(nu<<1)+1]+=lz[nu];
    124     lz[nu]=0;
    125 }
    126 //5 5
    127 //1 1 1 1 1
    128 //1 2 2 -1
    129 //3 1 5

    祝AC哟;

        

    Just close your eyes, you`ll be alright, no one can hurt you after you die.
  • 相关阅读:
    NO12 useradd-passwd-uname-hostname命令-上传rz下载sz-批量部署- Linux用户相关操作
    NO11 SSH故障排查思路和netstat命令
    NO10 查看Linux操作系统-版本-内核-Linux分区
    NO9 Linux快捷键整理及最常用命令
    NO8 find结合sed查找替换企业案例多方法精讲&命令总结!
    NO7 利用三剑客awk-grep-sed-head-tail等7种方法实践
    python 对比图片相似度
    MonkeyRunner 实现自动点击截屏后与本地图库进行对比输出
    monkeyrunner对比屏幕局部图像.getSubImage()
    锤子便签的 monkeyrunner 测试脚本(转)
  • 原文地址:https://www.cnblogs.com/nietzsche-oier/p/6218468.html
Copyright © 2011-2022 走看看