1、和与平方和在下传和更新时的先后次序是先平方和再和;
2、输入的原数组、所有被维护的数组以及更新时的 k 开double;
3、所有应下放的地方全已经下放;
目测区间和没有问题,问题大概率出在平方和上,AC on #5#6#7#8。
#include <iomanip>
#include <iostream>
using namespace std;
const int N = 1e5;
int n, m;
double a[N + 3];
namespace segment_tree {
double data1[(N << 2) + 3], data2[(N << 2) + 3], lz[(N << 2) + 3] = {0};
void build(int p, int l, int r) {
if (l == r) {
data1[p] = a[l], data2[p] = a[l] * a[l];
return;
}
int mid = l + r >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
data1[p] = data1[p << 1] + data1[p << 1 | 1];
data2[p] = data2[p << 1] + data2[p << 1 | 1];
return;
}
void pushdown(int p, int l, int r) {
int mid = l + r >> 1;
data2[p << 1] += 2.00 * lz[p] * data2[p << 1] + (mid - l + 1) * lz[p] * lz[p];
data2[p << 1 | 1] += 2.00 * lz[p] * data2[p << 1 | 1] + (r - mid) * lz[p] * lz[p];
data1[p << 1] += lz[p] * (mid - l + 1);
data1[p << 1 | 1] += lz[p] * (r - mid);
lz[p << 1] += lz[p];
lz[p << 1 | 1] += lz[p];
lz[p] = 0;
return;
}
void update(int p, int l, int r, int x, int y, double k) {
if (l >= x && r <= y) {
data2[p] += 2.00 * k * data1[p] + (r - l + 1) * k * k;
data1[p] += k * (r - l + 1);
lz[p] += k;
return;
}
if (lz[p]) pushdown(p, l, r);
int mid = l + r >> 1;
if (x <= mid) update(p << 1, l, mid, x, y, k);
if (y > mid) update(p << 1 | 1, mid + 1, r, x, y, k);
data1[p] = data1[p << 1] + data1[p << 1 | 1];
data2[p] = data2[p << 1] + data2[p << 1 | 1];
return;
}
double query1(int p, int l, int r, int x, int y) {
if (l >= x && r <= y) return data1[p];
if (lz[p]) pushdown(p, l, r);
double res = 0.00;
int mid = l + r >> 1;
if (x <= mid) res += query1(p << 1, l, mid, x, y);
if (y > mid) res += query1(p << 1 | 1, mid + 1, r, x, y);
return res;
}
double query2(int p, int l, int r, int x, int y) {
if (l >= x && r <= y) return data2[p];
if (lz[p]) pushdown(p, l, r);
double res = 0.00;
int mid = l + r >> 1;
if (x <= mid) res += query2(p << 1, l, mid, x, y);
if (y > mid) res += query2(p << 1 | 1, mid + 1, r, x, y);
return res;
}
}
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
segment_tree::build(1, 1, n);
while (m--) {
double k;
int op, x, y;
cin >> op;
switch (op) {
case 1:
cin >> x >> y >> k;
segment_tree::update(1, 1, n, x, y, k);
break;
case 2:
cin >> x >> y;
cout << fixed << setprecision(4) << segment_tree::query1(1, 1, n, x, y) / (y - x + 1) << '\n';
break;
case 3:
cin >> x >> y;
cout << fixed << setprecision(4) << segment_tree::query2(1, 1, n, x, y) / (y - x + 1)
- segment_tree::query1(1, 1, n, x, y) / (y - x + 1)
* segment_tree::query1(1, 1, n, x, y) / (y - x + 1) << '\n';
break;
}
}
return 0;
}