zoukankan      html  css  js  c++  java
  • 线段树维护区间平均值和方差

    传送门

    滚粗了的 HansBug 在收拾旧数学书,然而他发现了什么奇妙的东西。

    题目描述

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

    输入格式

    第一行包含两个正整数 N,M,分别表示数列中实数的个数和操作的个数。

    第二行包含 N 个实数,其中第 i 个实数表示数列的第 i 项。

    接下来 M 行,每行为一条操作,格式为以下三种之一:

    操作 11:1 x y k ,表示将第 x 到第 y 项每项加上 kk 为一实数。
    操作 22:2 x y ,表示求出第 x 到第 y 项这一子数列的平均数。
    操作 33:3 x y ,表示求出第 x 到第 y 项这一子数列的方差。

    输出格式

    输出包含若干行,每行为一个实数,即依次为每一次操作 22 或操作 33 所得的结果(所有结果四舍五入保留 44 位小数)。

    输入输出样例

    输入 #1
    5 5
    1 5 4 2 3
    2 1 4
    3 1 5
    1 1 1 1
    1 2 2 -1
    3 1 5
    
    输出 #1
    3.0000
    2.0000
    0.8000
    

     

     
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=1e6+100;
    double a[maxn];
    struct node{
        int l,r;//这个题不能维护区间平均值这样查询不对 
        double sum,p;///区间和,区间平方和 
        double lazy;
        double s;
    }t[maxn];
    void push_up(int p){
        t[p].sum=(t[2*p].sum+t[2*p+1].sum);
        t[p].p=(t[2*p].p+t[2*p+1].p);
    }
    void push_down(int p){
        
        t[2*p].p+=1.0*(t[2*p].s*t[p].lazy*t[p].lazy+t[2*p].sum*2*t[p].lazy);
        t[2*p+1].p+=1.0*(t[2*p+1].s*t[p].lazy*t[p].lazy+t[2*p+1].sum*2*t[p].lazy);
        
        t[2*p].sum+=1.0*(t[p].lazy*t[2*p].s);
        t[2*p+1].sum+=1.0*(t[p].lazy*t[2*p+1].s);
        
        t[2*p].lazy+=t[p].lazy;
        t[2*p+1].lazy+=t[p].lazy;
         
        t[p].lazy=0;
    }
    void build(int p,int l,int r){
        t[p].l=l;
        t[p].r=r;
        t[p].lazy=0;
        t[p].s=1.0*(t[p].r-t[p].l+1);
        if(l==r){
            t[p].sum=a[l];
            t[p].p=1.0*a[l]*a[l];
            return ;
        }
        int mid=(t[p].l+t[p].r)/2;
        build(2*p,l,mid);
        build(2*p+1,mid+1,r);
        push_up(p);
    }
    void add(int p,int l,int r,double k){
        if(t[p].l>=l&&t[p].r<=r){
            t[p].p+=(1.0*t[p].s*k*k+2.0*t[p].sum*k);
            t[p].sum+=1.0*(t[p].s*k); 
            t[p].lazy+=k;
            return ;
        }
        push_down(p);
        int mid=(t[p].l+t[p].r)/2;
        if(l<=mid){
            add(2*p,l,r,k);
        } 
        if(r>mid){
            add(2*p+1,l,r,k);
        }
        push_up(p);
    } 
    double querysum(int p,int l,int r){
        if(t[p].l>=l&&t[p].r<=r){
            return t[p].sum;
        }
        push_down(p);
        int mid=(t[p].l+t[p].r)/2;
        double ans=0; 
        if(l<=mid){
            ans+=querysum(2*p,l,r);
        } 
        if(r>mid){
            ans+=querysum(2*p+1,l,r); 
        }
        return ans;
    }
    double queryp(int p,int l,int r){
        if(t[p].l>=l&&t[p].r<=r){
            return t[p].p;
        }
        push_down(p);
        int mid=(t[p].l+t[p].r)/2;
        double ans=0;
        if(l<=mid){
            ans+=queryp(2*p,l,r); 
        }
        if(r>mid){
            ans+=queryp(2*p+1,l,r);
        }
        return ans;
    }
    int main(){
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        build(1,1,n);
        int op,x,y;
        double k;
        while(m--){
            scanf("%d",&op);
            if(op==1){
                scanf("%d%d%lf",&x,&y,&k);
                add(1,x,y,k);
            }
            if(op==2){
                scanf("%d%d",&x,&y);
                printf("%.4lf
    ",querysum(1,x,y)/(y-x+1));
            }
            if(op==3){
                scanf("%d%d",&x,&y);
                double sum=1.0*querysum(1,x,y);
                double eva=1.0*sum/(y-x+1);
                printf("%.4lf
    ",(queryp(1,x,y)-2*eva*sum+eva*eva*(y-x+1))/(y-x+1));
    //            double change=querysum(1,x,y)/(y-x+1);
    //            add(1,x,y,-change);
    //            printf("%.4lf
    ",queryp(1,x,y)/(y-x+1));
    //            add(1,x,y,change);
            }
        }
    } 
  • 相关阅读:
    浅谈Java中的equals和==与hashCode
    数组操作
    python-类
    javascript操控浏览器
    javascript_获取浏览器属性
    javascript_data
    python3_phantomJS_test
    python检测字符串的字母
    python百分比数比较大小
    selenium加载时间过长
  • 原文地址:https://www.cnblogs.com/lipu123/p/14645737.html
Copyright © 2011-2022 走看看