• luogu P1471(线段树)


    传送门

    题意:

    维护区间加区间查询平均数,区间查询方差。

    分析:

    维护区间平均数非常简单,根据式子(sum_{i=1}^{n}a_ifrac{1}{n})得知,我们只需要维护一个区间和即可。

    问题就在于维护方差,我们尝试将方差的式子化简一下:

    [frac{(a_1-overline{a})^2+(a_2-overline{a})^2+dots+ (a_n-overline{a})^2}{n} ]

    [=frac{a_i^2+a_2^2+dots+a_n^2-2*(a_1-overline{a})-2*(a_2-overline{a})-dots-2*(a_n-overline{a})+n*overline{a}^2}{n} ]

    [=frac{sum_{i=1}^{i=n}a_i^2-overline{a}*sum_{i=1}^{i=n}a_i+n*overline{a}^2}{n} ]

    [=frac{sum_{i=1}^{i=n}a_i^2}{n}-overline{a}^2 ]

    因此,我们发现此时,我们只需要维护一个区间的平方和以及区间的和即可。

    而对于区间平方和的维护,我们继续化简式子:

    [a_1^2+a_2^2+dots+a_n^2 ]

    [(a_1+k)^2+(a_2+k)^2+dots+(a_n+k)^2 ]

    [=a_1^2+a_2^2+dots+a_n^2+n*k^2+2*k*(a_1+a_2+dots+a_n) ]

    [=sum_{i=1}^{i=n}a_i^2+2*k*sum_{i=1}^{i=n}a_i+n*k^2 ]

    因此我们发现,每次区间更新(k)的时候,我们只需要增加(2*k*sum_{i=1}^{i=n}a_i+n*k^2),而这个值我们只需要维护一个区间加就可以完成。

    综上,我们直接可以用线段树去大力的维护。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define maxn 100005
    struct Node{
        double sum,mulsum,lazy;
        int len;
    }tr[maxn<<2];
    double a[maxn];
    void push_up(int rt){
        tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
        tr[rt].mulsum=tr[rt<<1].mulsum+tr[rt<<1|1].mulsum;
    }
    void push_down(int rt,int l,int r){
        if(tr[rt].lazy){
            tr[rt<<1].mulsum+=tr[rt<<1].len*tr[rt].lazy*tr[rt].lazy+ 2*tr[rt].lazy*tr[rt<<1].sum;
            tr[rt<<1|1].mulsum+=tr[rt<<1|1].len*tr[rt].lazy*tr[rt].lazy+ 2*tr[rt].lazy*tr[rt<<1|1].sum;
            tr[rt<<1].lazy+=tr[rt].lazy;
            tr[rt<<1|1].lazy+=tr[rt].lazy;
            tr[rt<<1].sum+=tr[rt].lazy*tr[rt<<1].len;
            tr[rt<<1|1].sum+=tr[rt].lazy*tr[rt<<1|1].len;
            tr[rt].lazy=0;
        }
    }
    void build(int l,int r,int rt){
        tr[rt].lazy=0;
        tr[rt].len=r-l+1;
        if(l==r){
            tr[rt].sum=a[l];
            tr[rt].mulsum=a[l]*a[l];
            tr[rt].len=r-l+1;
            return ;
        }
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
        push_up(rt);
    }
    void update(int L,int R,int l,int r,int rt,double add){
        if(L<=l&&R>=r){
            tr[rt].mulsum+=(r-l+1)*add*add+2.0*add*tr[rt].sum;
            tr[rt].sum+=(r-l+1)*add;
            tr[rt].lazy+=add;
            return ;
        }
        int mid=(l+r)>>1;
        push_down(rt,l,r);
        if(L<=mid) update(L,R,l,mid,rt<<1,add);
        if(R>mid) update(L,R,mid+1,r,rt<<1|1,add);
        push_up(rt);
    }
    double querysum(int L,int R,int l,int r,int rt){
        if(L<=l&&R>=r){
            return tr[rt].sum;
        }
        int mid=(l+r)>>1;
        double res=0;
        push_down(rt,l,r);
        if(L<=mid) res+=querysum(L,R,l,mid,rt<<1);
        if(R>mid) res+=querysum(L,R,mid+1,r,rt<<1|1);
        return res;
    }
    double querymulsum(int L,int R,int l,int r,int rt){
        if(L<=l&&R>=r){
            return tr[rt].mulsum;
        }
        int mid=(l+r)>>1;
        double res=0;
        push_down(rt,l,r);
        if(L<=mid) res+=querymulsum(L,R,l,mid,rt<<1);
        if(R>mid) res+=querymulsum(L,R,mid+1,r,rt<<1|1);
        return res;
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%lf",&a[i]);
        }
        build(1,n,1);
        while(m--){
            int opt,l,r;
            double add;
            scanf("%d%d%d",&opt,&l,&r);
            if(opt==1){
                scanf("%lf",&add);
                update(l,r,1,n,1,add);
            }
            else if(opt==2){
                double res=querysum(l,r,1,n,1);
                printf("%.4f
    ",1.0*res/(r-l+1));
            }
            else{
                double tmp=1.0*querysum(l,r,1,n,1)/(r-l+1);
                double res=1.0*querymulsum(l,r,1,n,1)/(r-l+1);
                res-=tmp*tmp;
                printf("%.4f
    ",res);
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    (原).NET程序加入多语言包解决方案工具,超级棒
    c++标准库中的四个智能指针比较
    Mongodb c++ API的测试和封装
    MongoDB的c++驱动安装痛苦历程
    GLC_Player DOWNLOAD
    MongoDB的连接、创库、删库、插入文档、更新文档
    非关系型数据库--MongoDB的安装及概念
    虚拟机的安装
    OpenGL ES 学习
    QT学习
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11160853.html
Copyright © 2020-2023  润新知