#include <iostream>
#include <cstring>
using namespace std;
#define ls (id << 1)
#define rs (id << 1 | 1)
#define mid ((l + r) >> 1)
const int maxn = 1e5 + 5;
int n, m;
struct Tree {
double v, tag, sq;
} t[maxn<<2];
void build(int l, int r, int id) {
if(l == r) {
scanf("%lf", &t[id].v);
t[id].sq = t[id].v * t[id].v;
}
else {
build(l, mid, ls); build(mid+1, r, rs);
t[id].v = t[ls].v + t[rs].v;
t[id].sq = t[ls].sq + t[rs].sq;
}
}
void pushup(int l, int r, int id) {
double k = t[id].tag;
t[ls].sq += 2*k*t[ls].v + k*k*(mid-l+1);
t[rs].sq += 2*k*t[rs].v + k*k*(r-mid);
t[ls].v += k * (mid-l+1);
t[rs].v += k * (r-mid);
t[ls].tag += k;
t[rs].tag += k;
t[id].tag = 0;
}
void add(int ql, int qr, int l, int r, int id, double k) {
if(ql <= l && r <= qr) {
t[id].sq += 2*k*t[id].v + (r-l+1)*k*k;
t[id].v += k*(r-l+1);
t[id].tag += k;
return;
}
if(t[id].tag) pushup(l, r, id);
if(ql <= mid) add(ql, qr, l, mid, ls, k);
if(mid < qr) add(ql, qr, mid+1, r, rs, k);
t[id].v = t[ls].v + t[rs].v;
t[id].sq = t[ls].sq + t[rs].sq;
}
double getsum(int ql, int qr, int l, int r, int id) {
if(ql <= l && r <= qr) return t[id].v;
if(t[id].tag) pushup(l, r, id);
double res = 0;
if(ql <= mid) res += getsum(ql, qr, l, mid, ls);
if(mid < qr) res += getsum(ql, qr, mid+1, r, rs);
return res;
}
double getsq(int ql, int qr, int l, int r, int id) {
if(ql <= l && r <= qr) return t[id].sq;
if(t[id].tag) pushup(l, r, id);
double res = 0;
if(ql <= mid) res += getsq(ql, qr, l, mid, ls);
if(mid < qr) res += getsq(ql, qr, mid+1, r, rs);
return res;
}
int main() {
scanf("%d %d", &n, &m);
build(1, n, 1);
for(int i = 1; i <= m; i++) {
int op, x, y;
scanf("%d %d %d", &op, &x, &y);
if(op == 1) {
double k;
scanf("%lf", &k);
add(x, y, 1, n, 1, k);
}
else if(op == 2)
printf("%.4lf\n", getsum(x, y, 1, n, 1) / (y-x+1));
else {
double sig = getsum(x, y, 1, n, 1);
double bar = sig / (y-x+1);
double sq = getsq(x, y, 1, n, 1);
printf("%.4lf\n", 1.0 * (sq - 2*bar*sig + n*bar*bar) / n);
}
}
return 0;
}