rt,小样例过了,第一组大数据出负数
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define L i<<1
#define R i<<1|1
#define for1(i,a,b) for(int i=(a);i<=(b);++i)
#define for2(i,a,b) for(int i=(a);i>=(b);--i)
#define FIO(a) freopen(#a".in","r",stdin);freopen(#a".out","w",stdout);
using namespace std;
typedef double db;
const int N=100010;
db a[N];
struct node{
int l,r;
db sum,squ,tag;
}tr[N<<2];
void upd(int i) {tr[i].sum=tr[L].sum+tr[R].sum,tr[i].squ=tr[L].squ+tr[R].squ;}
void build(int i,int l,int r) {
tr[i].l=l,tr[i].r=r,tr[i].sum=tr[i].squ=tr[i].tag=0;
if(l==r) return tr[i].sum=a[l],tr[i].squ=a[l]*a[l],void();
int mid=l+r>>1;
build(L,l,mid),build(R,mid+1,r),upd(i);
}
void pushdown(int i,int l,int r) {
if(tr[i].tag) {
int mid=l+r>>1;
tr[L].squ+=2*tr[i].tag*tr[L].sum+(mid-l+1)*tr[i].tag*tr[i].tag;
tr[L].sum+=(mid-l+1)*tr[i].tag,tr[L].tag+=tr[i].tag;
tr[R].squ+=2*tr[i].tag*tr[R].sum+(r-mid)*tr[i].tag*tr[i].tag;
tr[R].sum+=(r-mid)*tr[i].tag,tr[R].tag+=tr[i].tag,tr[i].tag=0;
}
}
void change(int i,int l,int r,db y) {
if(tr[i].l==l&&tr[i].r==r)
return tr[i].squ+=2*tr[i].sum*y+y*y*(r-l+1),tr[i].sum+=y*(r-l+1),tr[i].tag+=y,void();
pushdown(i,l,r);
int mid=tr[i].l+tr[i].r>>1;
if(r<=mid) change(L,l,r,y);
else if(l>mid) change(R,l,r,y);
else change(L,l,mid,y),change(R,mid+1,r,y);
upd(i);
}
db get(int i,int l,int r,bool type) {
if(tr[i].l==l&&tr[i].r==r) return type==1?tr[i].sum:tr[i].squ;
pushdown(i,l,r);
int mid=tr[i].l+tr[i].r>>1;
if(r<=mid) return get(L,l,r,type);
else if(l>mid) return get(R,l,r,type);
else return get(L,l,mid,type)+get(R,mid+1,r,type);
}
db k;
int n,m,op,l,r;
signed main () {
// FIO(P1471_1);
scanf("%d%d",&n,&m);
for1(i,1,n) scanf("%lf",a+i);
build(1,1,n);
while(m--) {
scanf("%d%d%d",&op,&l,&r);
switch(op) {
case 1:
scanf("%lf",&k),change(1,l,r,k);
break;
case 2:
printf("%.4lf\n",get(1,l,r,1)/(r-l+1));
break;
case 3:
db tmp=get(1,l,r,1)/(r-l+1);
printf("%.4lf\n",get(1,l,r,0)/(r-l+1)-tmp*tmp);
}
}
return 0;
}