• 方差


    题目背景

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

    题目描述

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

    输入输出格式

    输入格式:

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

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

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

    操作1:1 x y k ,表示将第x到第y项每项加上k,k为一实数。

    操作2:2 x y ,表示求出第x到第y项这一子数列的平均数。

    操作3:3 x y ,表示求出第x到第y项这一子数列的方差。

    输出格式:

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

    输入输出样例

    输入样例#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

    分析

    线段树,是个好东西呀,这道题很容易想到线段树维护,嘤嘤嘤,很好想到啊!!

    我去,发现,插入不了数学公式,插入不了任何有用的东西,烦死人,只好手打了呢!!

    额,好吧,我来插入图片啦!!




    图片取自luogu,感谢啦。
    由此可以看出只要用线段树维护区间和,和区间平方和即可,呃呃呃呃,当然还要个下推标记啦,烦死人。。。
    #include <cstdio>
    #include <cmath>
    #include <deque>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    
    const int Maxn=20041108;
    const int inf=20040207;
    const int I_LOVE_XYY=5201314
    
    int n,m,x,y,z;double k;
    struct node { int l,r; double w,v,s; }tree[Maxn*4];
    void build_tree(int index,int l,int r) {
        tree[index].l=l;
        tree[index].r=r;
        tree[index].w=tree[index].s=tree[index].v=0;
        if(l==r) {
            cin>>k;
            tree[index].w=k;
            tree[index].s=k*k;
            tree[index].v=k;
            return;
        }
        int mid=(l+r)/2;
        build_tree(index*2,l,mid);
        build_tree(index*2+1,mid+1,r);
        tree[index].w=tree[index*2].w+tree[index*2+1].w;
        tree[index].s=tree[index*2].s+tree[index*2+1].s;
    }
    void pushdown(int index) {
        if(tree[index].v) {
            tree[index*2].s+=2*tree[index].v*tree[index*2].w+(tree[index*2].r-tree[index*2].l+1)*tree[index].v*tree[index].v;
            tree[index*2+1].s+=2*tree[index].v*tree[index*2+1].w+(tree[index*2+1].r-tree[index*2+1].l+1)*tree[index].v*tree[index].v;
            tree[index*2].w+=tree[index].v*(tree[index*2].r-tree[index*2].l+1);
            tree[index*2+1].w+=tree[index].v*(tree[index*2+1].r-tree[index*2+1].l+1);
            tree[index*2].v+=tree[index].v;
            tree[index*2+1].v+=tree[index].v;
            tree[index].v=0;
        }
    }
    void change_tree(int index,int l,int r,double k) {
        if(tree[index].l>=l&&tree[index].r<=r) {
            tree[index].v+=k;
            tree[index].s+=2*k*tree[index].w+k*k*(tree[index].r-tree[index].l+1);
            tree[index].w+=k*(tree[index].r-tree[index].l+1);
            return;
        }
        int mid=(tree[index].l+tree[index].r)/2;
        pushdown(index);
        if(l<=mid) change_tree(index*2,l,r,k);
        if(r>mid) change_tree(index*2+1,l,r,k);
        tree[index].w=tree[index*2].w+tree[index*2+1].w;
        tree[index].s=tree[index*2].s+tree[index*2+1].s;
    }
    double query_x(int index,int l,int r) {
        if(tree[index].l>=l&&tree[index].r<=r) return tree[index].w;
        double ans=0;
        int mid=(tree[index].l+tree[index].r)/2;
        pushdown(index);
        if(l<=mid) ans+=query_x(index*2,l,r);
        if(r>mid) ans+=query_x(index*2+1,l,r);
        return ans;
    }    
    double query_y(int index,int l,int r) {
        if(tree[index].l>=l&&tree[index].r<=r) return tree[index].s;
        double ans=0;
        int mid=(tree[index].l+tree[index].r)/2;
        pushdown(index);
        if(l<=mid) ans+=query_y(index*2,l,r);
        if(r>mid) ans+=query_y(index*2+1,l,r);
        return ans;
    }    
    int main() {
        cin>>n>>m;
        build_tree(1,1,n);
        while(m--) {
            cin>>z>>x>>y;
            if(z==1) {
                cin>>k;
                change_tree(1,x,y,k);
            }
            else if(z==2) printf("%.4lf
    ",query_x(1,x,y)/(y-x+1));
            else {
                double dx=query_x(1,x,y)/(y-x+1);
                double dy=query_y(1,x,y)/(y-x+1);
                printf("%.4lf
    ",dy-dx*dx); 
            }    
        }
        return 0;
    }

    下推标记和查询输出,可以看出充分利用了上述两个公式来操作,是个不错的题目,qwq。。。

    此题需要数学期末考试在145以上的同学才可以尝哟!!

    因为我都不会啊啊啊啊,那是不可能的,但我考不到145也会做,哈哈哈哈哈!!!

     
  • 相关阅读:
    第一篇博客
    【面试大系】PHP程序员的知识盘点
    【PHP资源】PHP 资源大全
    【前端经纬】将页面元素定位
    大爱卡农三百年
    【夯实PHP基础】PHP标准库 SPL
    【http抓包】记录一次抓手机app的接口
    【算法】PHP实现冒泡排序和快速排序--防遗忘
    Apache的初中级面试题
    【生活感悟系列】感悟在一瞬间(不断完善中)
  • 原文地址:https://www.cnblogs.com/Shen-Yu/p/9886660.html
Copyright © 2020-2023  润新知