方差

链接:https://www.luogu.org/problemnew/show/P1471

题解:

对式子进行一些化简就会发现等价于在求方差

裸的线段树

#include <bits/stdc++.h>
using namespace std;
#define maxn 111111
#define mid (p[x].h+p[x].t)/2
int n,m;
double a[maxn],b[maxn];
struct re
{
    int h,t;
    double x1,x2,lazy;
}p[maxn*4];
void updata(int x)
{
    p[x].x1=p[x*2].x1+p[x*2+1].x1;
    p[x].x2=p[x*2].x2+p[x*2+1].x2;
}
void build(int x,int h,int t)
{
    p[x].h=h; p[x].t=t;
    if (h==t)
    {
        p[x].x1=a[h]; p[x].x2=b[h];
        return;
    }
    build(x*2,h,mid); build(x*2+1,mid+1,t);
    updata(x);
}
void down(int x)
{
    if (p[x].lazy)
    { 
        p[x].x2+=2*p[x].x1*p[x].lazy+(p[x].t-p[x].h+1)*p[x].lazy*p[x].lazy;
        p[x].x1+=(p[x].t-p[x].h+1)*p[x].lazy;
        if (p[x].h!=p[x].t)
        {
          p[x*2].lazy+=p[x].lazy;
          p[x*2+1].lazy+=p[x].lazy;    
        } 
        p[x].lazy=0;
    }
}
void change(int x,int h,int t,double sum)
{
    down(x);
    if (p[x].h>t||p[x].t<h) return;
    if (h<=p[x].h&&p[x].t<=t)
    {
        p[x].lazy+=sum; down(x);
        return;
    }
    change(x*2,h,t,sum); change(x*2+1,h,t,sum);
    updata(x);
}
double query1(int x,int h,int t)
{
    down(x);
    if (p[x].h>t||p[x].t<h) return(0);
    if (h<=p[x].h&&p[x].t<=t)
    {
        return(p[x].x1);
    } 
    return(query1(x*2,h,t)+query1(x*2+1,h,t));
}
double query2(int x,int h,int t)
{
    down(x);
    if (p[x].h>t||p[x].t<h) return(0);
    if (h<=p[x].h&&p[x].t<=t)
    {
        return(p[x].x2);
    } 
    return(query2(x*2,h,t)+query2(x*2+1,h,t));
}
int main()
{
    std::ios::sync_with_stdio(false);
    cin>>n>>m;
    for (int i=1;i<=n;i++)
    {  
      cin>>a[i]; b[i]=(a[i]*a[i]);
    }
    build(1,1,n);
    for (int i=1;i<=m;i++)
    {
        int c,d,e; double f;
        cin>>c;
        if (c==1)
        {
            cin>>d>>e>>f;
            change(1,d,e,f);
        }
        if (c==2)
        {
            cin>>d>>e;
            printf("%.4f\n",query1(1,d,e)/(e-d+1));
        }
        if (c==3)
        {
            cin>>d>>e;
            double x=query1(1,d,e),y=x/(e-d+1);
            printf("%.4f\n",(query2(1,d,e)-2*y*x)/(e-d+1)+y*y);
        }
    }
}

 

posted @ 2018-02-01 22:14  尹吴潇  阅读(164)  评论(0编辑  收藏  举报