#include <bits/stdc++.h>
using namespace std;
constexpr int N = 1e5 + 5; long double arr[N], k; int n, m, op_type, l, r;
struct SegmentTree { public: struct Node { int l, r; long double sum_square, sum, add; }; Node tr[N << 2]; void lazy(int k, long double value) { tr[k].sum_square += tr[k].sum * 2 * value + (tr[k].r - tr[k].l + 1) * value * value; tr[k].sum += (tr[k].r - tr[k].l + 1) * value; tr[k].add += value; } void push_up(int k) { int lc = k << 1, rc = k << 1 | 1; tr[k].sum_square = tr[lc].sum_square + tr[rc].sum_square; tr[k].sum = tr[lc].sum + tr[rc].sum; } void push_down(int k) { if (tr[k].add == 0) { return void(); } int lc = k << 1, rc = k << 1 | 1; lazy(lc, tr[k].add); lazy(rc, tr[k].add); tr[k].add = 0; } void build_tree(int k, int l, int r) { tr[k].l = l, tr[k].r = r; tr[k].sum = tr[k].sum_square = tr[k].add = 0; if (tr[k].l == tr[k].r) { tr[k].sum = arr[l]; tr[k].sum_square = arr[l] * arr[l]; return void(); } int mid = (tr[k].l + tr[k].r) >> 1; int lc = k << 1, rc = k << 1 | 1; build_tree(lc, l, mid); build_tree(rc, mid + 1, r); push_up(k); } void modify(int k, int l, int r, long double value) { if (tr[k].l >= l && tr[k].r <= r) { lazy(k, value); return void(); } push_down(k); int mid = (tr[k].l + tr[k].r) >> 1; int lc = k << 1, rc = k << 1 | 1; if (r <= mid) { modify(lc, l, r, value); } else if (l > mid) { modify(rc, l, r, value); } else { modify(lc, l, mid, value); modify(rc, mid + 1, r, value); } push_up(k); } long double __query_sum(int k, int l, int r) { if (tr[k].l >= l && tr[k].r <= r) { return tr[k].sum; } push_down(k); int mid = (tr[k].l + tr[k].r) >> 1; int lc = k << 1, rc = k << 1 | 1; if (r <= mid) { return __query_sum(lc, l, r); } else if (l > mid) { return __query_sum(rc, l, r); } else { return __query_sum(lc, l, mid) + __query_sum(rc, mid + 1, r); } } long double __query_sum_square(int k, int l, int r) { if (tr[k].l >= l && tr[k].r <= r) { return tr[k].sum_square; } push_down(k); int mid = (tr[k].l + tr[k].r) >> 1; int lc = k << 1, rc = k << 1 | 1; if (r <= mid) { return __query_sum_square(lc, l, r); } else if (l > mid) { return __query_sum_square(rc, l, r); } else { return __query_sum_square(lc, l, mid) + __query_sum_square(rc, mid + 1, r); } } long double query_average(int l, int r) { long double sum = __query_sum(1, l, r); return sum / (long double) (r - l + 1); } long double query_variance(int l, int r) { long double average = query_average(l, r); long double sum = __query_sum(1, l, r); long double sum_square = __query_sum_square(1, l, r); int length = r - l + 1; return (sum_square - 2 * average * sum + length * average * average) / (long double) length; } } segment_tree;
int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cin >> n >> m; for (int i = 1; i <= n; i ++) { cin >> arr[i]; } segment_tree.build_tree(1, 1, n); while (m --) { cin >> op_type >> l >> r; if (op_type == 1) { cin >> k; segment_tree.modify(1, l, r, k); } else if (op_type == 2) { long double result = segment_tree.query_average(l, r); result = round(result * 10000) / (long double) 10000; cout << setiosflags(ios::fixed) << setprecision(4) << result << '\n'; } else if (op_type == 3) { long double result = segment_tree.query_variance(l, r); result = round(result * 10000) / (long double) 10000; cout << setiosflags(ios::fixed) << setprecision(4) << result << '\n'; } } return 0; }
|