rt,本人太 JuRuo 了,裸的线段树板子都 0pts WA,求大佬调一下。
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define db double
#define inf 0x3f3f3f3f
#define infi 0x3f3f3f3f3f3f3f3fll
#define up(i,x,y) for(register int i=x;i<=y;++i)
#define dn(i,x,y) for(register int i=x;i>=y;--i)
using namespace std;
inline int read(){int x=0;bool f=0;char ch=getchar();while(!isdigit(ch)){f|=(ch=='-');ch=getchar();}while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();return (f?-x:x);}
inline void write(int x){if(x<0)putchar('-'),x=-x;if(x>9)write(x/10);putchar(x%10|48);}
inline void writeln(int x){write(x),putchar('\n');}
inline void writesp(int x){write(x),putchar(' ');}
#define min(a ,b) a < b ? a : b
#define max(a ,b) a > b ? a : b
const int N = 1e5 + 10;
struct SGT{int l,r;double sum;}tr[N << 2] ,tr1[N << 2];
double lazy[N << 2];
inline void pushup(int u){tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum , tr1[u].sum = tr1[u << 1].sum + tr1[u << 1 | 1].sum;}
int n ,Q ,a[N];
inline void pushdown(int u){
if(!lazy[u]) return;
int len = tr[u].r - tr[u].l + 1;
tr1[u << 1].sum += 2 * lazy[u] * tr[u << 1].sum + (tr1[u << 1].r - tr1[u << 1].l + 1) * lazy[u] * lazy[u];
tr1[u << 1 | 1].sum += 2 * lazy[u] * tr[u << 1 | 1].sum + (tr1[u << 1 | 1].r - tr1[u << 1 | 1].l + 1) * lazy[u] * lazy[u];
tr[u << 1].sum += (tr1[u << 1].r - tr1[u << 1].l + 1) * lazy[u];
tr[u << 1 | 1].sum += (tr1[u << 1 | 1].r - tr1[u << 1 | 1].l + 1) * lazy[u];
lazy[u << 1] += lazy[u];
lazy[u << 1 | 1] += lazy[u];
lazy[u] = 0;
} inline void build(int u,int L,int R){
tr[u].l = tr1[u].l = L ,tr[u].r = tr1[u].r = R;
if(L == R){tr[u].sum = a[L] , tr1[u].sum = a[L] * a[L];return;}
int mid = ((L + R) >> 1ll);
build(u << 1 ,L ,mid);
build(u << 1 | 1, mid + 1, R);
pushup(u);
} inline double query_sum(int u,int L,int R){
int l = tr[u].l ,r = tr[u].r;
if(l >= L && r <= R) return tr[u].sum;
pushdown(u);
int mid = ((l + r) >> 1);
double val = 0;
if(L <= mid) val += query_sum(u << 1 , L ,R);
if(mid < R) val += query_sum(u << 1 | 1 ,L ,R);
return val;
} inline double query_sqr(int u,int L,int R){
int l = tr1[u].l ,r = tr1[u].r;
if(l >= L && r <= R) return tr1[u].sum;
pushdown(u);
int mid = ((l + r) >> 1);
double val = 0;
if(L <= mid) val += query_sqr(u << 1 , L ,R);
if(mid < R) val += query_sqr(u << 1 | 1 ,L ,R);
return val;
} inline void update(int u,int L,int R,double v){
int l = tr[u].l ,r = tr[u].r;
if(l >= L && r <= R){
tr1[u].sum += 2 * v * tr[u].sum + v * v * (r - l + 1);
tr[u].sum += (r - l + 1) * v;
lazy[u] += v;
return;
}
pushdown(u);
int mid = ((l + r) >> 1);
if(L <= mid) update(u << 1 ,L ,R ,v);
if(mid < R) update(u << 1 | 1, L ,R ,v);
pushup(u);
} signed main(){
n = read() , Q = read();
up(i,1,n) cin >> a[i];
build(1, 1, n);
while(Q --){
int op = read();
double L ,R ,k;
cin >> L >> R;
if(op == 1) cin >> k;
if(op == 1) update(1 ,L ,R ,k);
if(op == 2) printf("%.4lf\n",query_sum(1 ,L ,R) / (R - L + 1));
if(op == 3){
double res1 = query_sqr(1 ,L ,R) / (R - L + 1) ,res2 = query_sum(1 ,L ,R) / (R - L + 1);
double res = res1 - res2 * res2;
printf("%.4lf\n",res);
}
}
return 0;
}