原题链接
- 题解:手推一下就知道了是要维护一个平方和的序列,然后就大力码码码。
- 代码:
#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
typedef long long ll;
const ll inf = 0x3f3f3f3f;
const ll N = 1e5 + 9;
typedef long double lb;
const lb eps = 1e-7;
lb a[N];
struct segment_tree{
struct node {
ll l, r, L, R;
lb data1, data2, lazy;
}tr[N << 2];
void pushup(ll p) {
tr[p].data1 = tr[tr[p].l].data1 + tr[tr[p].r].data1;
tr[p].data2 = tr[tr[p].l].data2 + tr[tr[p].r].data2;
return;
}
void pushdown(ll p) {
lb b = tr[p].lazy;
tr[p].lazy = 0.0;
ll L = tr[p].l;
ll R = tr[p].r;
tr[L].data2 += tr[L].data1*2.0*b +b* b * (tr[L].R - tr[L].L + 1.0);
tr[R].data2 += tr[R].data1 * 2.0 * b + b * b * (tr[R].R - tr[R].L + 1.0);
tr[L].data1 += (tr[L].R - tr[L].L + 1.0) * b;
tr[R].data1 += (tr[R].R - tr[R].L + 1.0) * b;
tr[L].lazy += b;
tr[R].lazy += b;
return;
}
void build(ll l, ll r, ll p) {
tr[p].l = p << 1;
tr[p].r = p << 1 | 1;
tr[p].L = l, tr[p].R = r;
if (l == r) {
tr[p].data1 = a[l];
tr[p].data2 = a[l] * a[l];
return;
}
lb mid = l + r >> 1;
build(l, mid, tr[p].l);
build(mid + 1, r, tr[p].r);
pushup(p);
}
void add(ll l, ll r, lb num, ll p) {
if (tr[p].L >= l && tr[p].R <= r) {
tr[p].data2 += 2.0 * num * tr[p].data1 + num * num * (tr[p].R - tr[p].L + 1.0);
tr[p].data1 += num * (lb)(tr[p].R - tr[p].L + 1.0);
tr[p].lazy += num;
return;
}
pushdown(p);
if (tr[tr[p].l].R >= l)add(l, r, num, tr[p].l);
if (tr[tr[p].r].L <= r)add(l, r, num, tr[p].r);
pushup(p);
}
lb ask(ll l, ll r, ll p, ll op) {
if (tr[p].L >= l && tr[p].R <= r) {
if (op==1)
return tr[p].data1;
return tr[p].data2;
}
pushdown(p);
lb ret = 0;
if (tr[tr[p].l].R >= l)ret += ask(l, r, tr[p].l, op);
if (tr[tr[p].r].L <= r)ret += ask(l, r, tr[p].r, op);
return ret;
}
}T;
signed main() {
ll n, m;
scanf("%lld%lld", &n, &m);
for (int i = 1; i <= n; i ++)scanf("%Lf", &a[i]);// cout << a[i] << " ";
T.build(1, n, 1);
while (m--) {
ll op;
scanf("%lld", &op);
if (op == 1) {
ll l, r;
lb x;
scanf("%lld%lld%Lf", &l, &r, &x);
T.add(l, r, x, 1);
}
else if (op == 2) {
ll l, r;
scanf("%lld%lld", &l, &r);
printf("%.4Lf
", T.ask(l, r, 1, 1) * 1.0/(r-l + 1.0));
}
else {
ll l, r;
scanf("%lld%lld", &l, &r);
lb sum = T.ask(l, r, 1, 2);
lb av = T.ask(l, r, 1, 1) * 1.0/(r-l + 1.0);
lb len = r-l + 1;
lb x = sum - 2 *T.ask(l, r, 1, 1) * av + len * av * av;
printf("%.4Lf
", x / len);
}
}
}