码迷,mamicode.com
首页 > 其他好文 > 详细

[Luogu] 方差

时间:2018-03-03 22:28:48      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:define   while   line   namespace   names   方差   www.   new   www   

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

线段树维护区间数的平方之和与和

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;

#define DB double
#define gc getchar()
#define lson jd << 1
#define rson jd << 1 | 1 

int n, m;
DB Answer, x_, imp_, W[N << 2], F[N << 2], A_2[N << 2], size[N << 2];

struct Read {
    inline int read_int() {
        int x = 0; char c = gc;
        while(c < 0 || c > 9) c = gc;
        while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = gc;
        return x;
    }
    inline DB read_DB() {DB x; scanf("%lf", &x); return x;}
}ac;

void Build_tree(int l, int r, int jd) {
    size[jd] = (r - l + 1);
    if(l == r) {
        W[jd] = ac.read_DB();
        A_2[jd] = W[jd] * W[jd]; 
        return ;
    }
    int mid = (l + r) >> 1;
    Build_tree(l, mid, lson);
    Build_tree(mid + 1, r, rson);
    W[jd] = W[lson] + W[rson];
    A_2[jd] = A_2[lson] + A_2[rson];
}
                      
void Down(int jd) {
    DB yj = F[jd];
    F[lson] += yj; F[rson] += yj;
    A_2[lson] += (2 * yj * W[lson] + size[lson] * yj * yj);
    A_2[rson] += (2 * yj * W[rson] + size[rson] * yj * yj);
    W[lson] += size[lson] * yj;
    W[rson] += size[rson] * yj;
    F[jd] = 0;
}

void Sec_G(int l, int r, int jd, int x, int y, DB yj) {
    if(x <= l && r <= y) {
        F[jd] += yj;
        A_2[jd] += (2 * yj * W[jd] + size[jd] * yj * yj);
        W[jd] += size[jd] * yj;
        return ;
    }
    if(F[jd]) Down(jd);
    int mid = (l + r) >> 1;
    if(x <= mid) Sec_G(l, mid, lson, x, y, yj);
    if(y > mid)  Sec_G(mid + 1, r, rson, x, y, yj);
    W[jd] = W[lson] + W[rson];
    A_2[jd] = A_2[lson] + A_2[rson]; 
} 

void Sec_A_w(int l, int r, int jd, int x, int y) {
    if(x <= l && r <= y) {
        Answer += W[jd];
        return ;
    } 
    if(F[jd]) Down(jd);
    int mid = (l + r) >> 1;
    if(x <= mid) Sec_A_w(l, mid, lson, x, y);
    if(y > mid)  Sec_A_w(mid + 1, r, rson, x, y); 
}

void Sec_A_A(int l, int r, int jd, int x, int y) {
    if(x <= l && r <= y) {
        imp_ += A_2[jd];
        return ;
    } 
    if(F[jd]) Down(jd);
    int mid = (l + r) >> 1;
    if(x <= mid) Sec_A_A(l, mid, lson, x, y);
    if(y > mid)  Sec_A_A(mid + 1, r, rson, x, y); 
}

int main() {
    n = ac.read_int();
    m = ac.read_int();
    Build_tree(1, n, 1);
    while(m --) {
        int opt = ac.read_int();
        if(opt == 1) {
            int x = ac.read_int(), y = ac.read_int(), k = ac.read_DB();
            Sec_G(1, n, 1, x, y, k);
        } else if(opt == 2) {
            Answer = 0;
            int x = ac.read_int(), y = ac.read_int();
            Sec_A_w(1, n, 1, x, y);
            printf("%.4lf\n", Answer / (y - x + 1));
        } else {
            Answer = 0;
            int x = ac.read_int(), y = ac.read_int();
            Sec_A_w(1, n, 1, x, y);
            x_ = Answer / (y - x + 1);
            imp_ = 0;
            Sec_A_A(1, n, 1, x, y);
            DB answer = imp_ - 2 * x_ * Answer + (y - x + 1) * x_ * x_;
            printf("%.4lf\n", answer / (y - x + 1));
        }
    }
    return 0;
}

                                                                     

[Luogu] 方差

标签:define   while   line   namespace   names   方差   www.   new   www   

原文地址:https://www.cnblogs.com/shandongs1/p/8503182.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!