[Luo Gu 5142] interval variance explanations

Foreword

This is a segment tree board title.

answer

We observed the expression
\ [AVG = \ n-FRAC {} {}. 1 \ sum_ = {I}. 1 ^ n-a_i \]
\ [D = \ {n-FRAC {}}. 1 \ sum_ = {I}. 1 ^ n- (a_i-avg) ^ 2 \
] we expand it into
\ [d = \ frac {1 } {n} \ sum_ {i = 1} ^ n (a_i ^ 2-2 \ times a_i \ times avg - avg ^ 2) \]
proposed to obtain a constant term
\ [d = \ frac {1 } {n} (\ sum_ {i = 1} ^ n a_i ^ 2-2 \ times avg \ times \ sum_ {i = 1} ^ n a_i + n \ times avg ^ 2
) \] then we opened two tree line, a maintenance \ (a_i \) and, a maintenance \ (a_i ^ 2 \) and, in addition a multiplicative inverse , ie can.
Bloggers also result konjac WA once, becauseModulo sedentary

Code

Two tree line on the deal together, is very convenient.
Inverse statement in accordance with the giant man, with a quick power (Goodbye Top Euro).

#include <cstdio>
#define ll long long

ll s[400005], s2[400005];
const ll MOD = 1e9 + 7;

ll read(){
    ll x = 0; int zf = 1; char ch = ' ';
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') zf = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
}

ll getInv(ll x){
    ll res = 1;
    for (int y = MOD - 2; y; y >>= 1, x = (x * x) % MOD)
        if (y & 1)
            (res *= x) %= MOD;
    return res;
}

void build(int pos, int l, int r){
    if (l == r){
        s[pos] = read(); s2[pos] = (s[pos] * s[pos]) % MOD;
        return ;
    }
    int mid = (l + r) >> 1;
    build(pos << 1, l, mid);
    build(pos << 1 | 1, mid + 1, r);
    s[pos] = s[pos << 1] + s[pos << 1 | 1];
    s2[pos] = s2[pos << 1] + s2[pos << 1 | 1];
}

ll query(int pos, int l, int r, int x, int y){
    if (x <= l && r <= y)
        return s[pos];
    ll ans = 0; int mid = (l + r) >> 1;
    if (x <= mid)
        ans += query(pos << 1, l, mid, x, y);
    if (mid < y)
        (ans += query(pos << 1 | 1, mid + 1, r, x, y)) %= MOD;
    return ans;
}

ll query2(int pos, int l, int r, int x, int y){
    if (x <= l && r <= y)
        return s2[pos];
    ll ans = 0; int mid = (l + r) >> 1;
    if (x <= mid)
        ans += query2(pos << 1, l, mid, x, y);
    if (mid < y)
        (ans += query2(pos << 1 | 1, mid + 1, r, x, y)) %= MOD;
    return ans;
}

void modify(int pos, int l, int r, int x, ll val){
    if (l == r){
        s[pos] = val, s2[pos] = (val * val) % MOD;
        return ;
    }
    int mid = (l + r) >> 1;
    if (x <= mid)
        modify(pos << 1, l, mid, x, val);
    else if (mid < x)
        modify(pos << 1 | 1, mid + 1, r, x, val);
    s[pos] = (s[pos << 1] + s[pos << 1 | 1]) % MOD;
    s2[pos] = (s2[pos << 1] + s2[pos << 1 | 1]) % MOD;
}

int main(){
    int n = read(), m = read();
    build(1, 1, n); ll c, a, b;
    while (m--){
        c = read(), a = read(), b = read();
        if (c == 1)
            modify(1, 1, n, a, b);
        else if (c == 2){
            ll ans2 = query2(1, 1, n, a, b), ans = query(1, 1, n, a, b);
            ll avg = (ans * getInv(b - a + 1)) % MOD;
            ll res = (((ans2 - (avg * ans * 2ll % MOD) + ((((avg * avg) % MOD) * (b - a + 1)) % MOD)) % MOD * getInv(b - a + 1))) % MOD;
            while (res < 0) res += MOD;
            printf("%lld\n", res);
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/linzhengmin/p/11128621.html