RT
没用题解区给的大部分做法,而是用的某教材上的分层方差求总方差的 将两组数据方差合并 的方法。
交了一发,平均值没出错
求助
#include <bits/stdc++.h>
#define LF double
#define ls t << 1
#define rs t << 1 | 1
const int Maxn = 1e5 + 5;
namespace Basic {
template <typename Temp>
inline void read(Temp & res) {
Temp fh = 1; res = 0; char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') fh = -1;
for(; isdigit(ch); ch = getchar()) res = (res << 3) + (res << 1) + (ch ^ '0');
res = res * fh;
}
template <typename Temp>
inline void readf(Temp & res) {
Temp fh = 1; res = 0; char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') fh = -1;
for(; isdigit(ch); ch = getchar()) res = res * 10 + (ch ^ '0');
if(ch != '.') {res = res * fh; return;}
ch = getchar(); for(Temp base = 0.1; isdigit(ch); ch = getchar(), base = base / 10) res = res + (ch ^ '0') * base;
res = res * fh;
}
template <typename Temp> inline void Checkmax(Temp & num, Temp comp) {if(comp > num) num = comp;}
template <typename Temp> inline void Checkmin(Temp & num, Temp comp) {if(comp < num) num = comp;}
}
using namespace Basic;
using namespace std;
struct Seg {
LF average;
LF data;
LF tag;
LF siz;
Seg() {average = data = tag = 0;}
} a[Maxn << 2];
LF num[Maxn];
int n, m, opt, x, y;
LF k;
inline Seg merge(Seg L, Seg R) {
Seg res; LF P = L.siz * R.siz / (L.siz + R.siz);
res.average = (L.siz * L.average + R.siz * R.average) / (L.siz + R.siz);
res.data = (L.data + R.data + P * (L.average - R.average) * (L.average - R.average)) / (L.siz + R.siz);
res.siz = L.siz + R.siz;
return res;
}
inline void pushup(int t) {
a[t] = merge(a[ls], a[rs]);
}
inline void pushdown(int t) {
a[ls].average += a[t].tag; a[rs].average += a[t].tag;
a[ls].tag += a[t].tag; a[rs].tag += a[t].tag;
a[t].tag = 0;
}
void build(int l, int r, int t) {
if(l == r) {
a[t].data = 0;
a[t].average = num[l];
a[t].tag = 0;
a[t].siz = 1;
return;
}
int mid = (l + r) >> 1;
build(l, mid, ls);
build(mid + 1, r, rs);
pushup(t);
}
void modify(int lf, int rt, LF add, int l, int r, int t) {
if((lf <= l) && (r <= rt)) {
a[t].average += add;
a[t].tag += add;
return;
}
pushdown(t);
int mid = (l + r) >> 1;
if(lf <= mid) modify(lf, rt, add, l, mid, ls);
if(rt > mid) modify(lf, rt, add, mid + 1, r, rs);
pushup(t);
}
Seg query(int lf, int rt, int l, int r, int t) {
if((lf <= l) && (r <= rt)) return a[t];
int mid = (l + r) >> 1; pushdown(t);
if(rt <= mid) return query(lf, rt, l, mid, ls);
if(lf > mid) return query(lf, rt, mid + 1, r, rs);
return merge(query(lf, rt, l, mid, ls), query(lf, rt, mid + 1, r, rs));
}
int main() {
cin >> n >> m;
for(register int i = 1; i <= n; ++i) cin >> num[i];
build(1, n, 1);
while(m--) {
cin >> opt;
if(opt == 1) {
cin >> x >> y >> k;
modify(x, y, k, 1, n, 1);
} else if(opt == 2) {
cin >> x >> y;
printf("%.4lf\n", query(x, y, 1, n, 1).average);
} else {
cin >> x >> y;
printf("%.4lf\n", query(x, y, 1, n, 1).data);
}
}
return 0;
}