额,本地可过可能不敢说,至少第一个测试点事对的~~(我也只能看到第一个测试点了,因为 RE 了)~~
#include <bits/stdc++.h>
const int N = 1000010;
#define int long long
const int mod = 998244353;
const int inf = 0x7fffffffffffff;
using namespace std;
int n, Q;
double a[N];
inline int read()
{
int t;
scanf("%lld", &t);
return t;
}
inline double double_read()
{
double t;
scanf("%lf", &t);
return t;
}
struct Seg{
int l, r;
double sum, fms, tag;
#define l(p) tree[p].l
#define r(p) tree[p].r
#define sum(p) tree[p].sum
#define fms(p) tree[p].fms
#define tag(p) tree[p].tag
}tree[N << 2];
void build(int p, int l, int r)
{
l(p) = l, r(p) = r;
if(l == r)
{
sum(p) = a[l];
fms(p) = a[l] * a[l];
return;
}
int mid = l + r >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
sum(p) = sum(p << 1) + sum(p << 1 | 1);
fms(p) = fms(p << 1) + fms(p << 1 | 1);
}
inline void Spread(int p)
{
if(tag(p))
{
fms(p << 1) += tag(p) * 2 * sum(p << 1) + tag(p) * tag(p) * (r(p << 1) - l(p << 1) + 1);
fms(p << 1 | 1) += tag(p) * 2 * sum(p << 1 | 1) + tag(p) * tag(p) * (r(p << 1 | 1) - l(p << 1 | 1) + 1);
sum(p << 1) += (r(p << 1) - l(p << 1) + 1) * tag(p);
sum(p << 1 | 1) += (r(p << 1 | 1) - l(p << 1 | 1) + 1) * tag(p);
tag(p << 1) += tag(p);
tag(p << 1 | 1) += tag(p);
tag(p) = 0;
}
}
void mtf(int p, int l, int r, double c)
{
if(l(p) >= l and r(p) <= r)
{
tag(p) += c;
fms(p) += 2 * c * sum(p) + c * c * (r(p) - l(p) + 1);
sum(p) += (r(p) - l(p) + 1) * c;
return;
}
Spread(p);
int mid = l(p) + r(p) >> 1;
if(l <= mid) mtf(p << 1, l, r, c);
if(r > mid) mtf(p << 1 | 1, l, r, c);
sum(p) = sum(p << 1) + sum(p << 1 | 1);
fms(p) = fms(p << 1) + fms(p << 1 | 1);
}
double qry(int p, int l, int r, bool op)
{
if(l(p) >= l and r(p) <= r) return op ? fms(p) : sum(p);
Spread(p);
int mid = l(p) + r(p) >> 1;
double Val = 0.0;
if(l <= mid) Val += qry(p << 1, l, r, op);
if(r > mid) Val += qry(p << 1 | 1, l, r, op);
return Val;
}
signed main()
{
freopen("data.in", "r", stdin);
n = read(), Q = read();
for(int i = 1;i <= n;i = -~i) a[i] = double_read();
build(1, 1, n);
while(Q --)
{
int op = read();
if(op == 1)
{
int l = read(), r = read();
double c = double_read();
mtf(1, l, r, c);
}
else if(op == 2)
{
int l = read(), r = read();
double Sum = qry(1, l, r, 0); // 取出这段区间的和
printf("%.4lf\n", Sum / (1.0 * (r - l + 1)));
}
else
{
int l = read(), r = read();
double Fms = qry(1, l, r, 1);
double Sum = qry(1, l, r, 0);
double xba = Sum / (1.0 * (r - l + 1)); // 平均数
printf("%.4lf\n", (Fms - xba * 2 * Sum + (r - l + 1) * xba * xba) / (1.0 * (r - l + 1)));
}
}
return 0;
}