#include<bits/stdc++.h>
#define ls(x) x<<1
#define rs(x) x<<1|1
using namespace std;
const int maxn=1e5+10;
int n,m;
double a[maxn];
struct node{
int l,r;
double sum,sq,lzy;
}tree[maxn<<2];
inline int read(){
int res=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
return res*w;
}
void push_up(int x){
tree[x].sum=tree[ls(x)].sum+tree[rs(x)].sum;
tree[x].sq=tree[ls(x)].sq+tree[rs(x)].sq;
}
void build(int x,int l,int r){
tree[x].l=l,tree[x].r=r;
if(l==r){
tree[x].sum=a[l],tree[x].sq=a[l]*a[l];
return;
}
int mid=(tree[x].l+tree[x].r)>>1;
build(ls(x),l,mid);
build(rs(x),mid+1,r);
push_up(x);
}
void push_down(int x){
int mid=(tree[x].l+tree[x].r)>>1;
tree[ls(x)].sq+=2*tree[x].lzy*tree[x].lzy+(mid-tree[x].l+1)*tree[x].lzy*tree[x].lzy;
tree[ls(x)].sum+=(mid-tree[x].l+1)*tree[x].lzy;
tree[ls(x)].lzy+=tree[x].lzy;
tree[rs(x)].sq+=2*tree[x].lzy*tree[x].lzy+(tree[x].r-mid+1)*tree[x].lzy*tree[x].lzy;
tree[rs(x)].sum+=(tree[x].r-mid+1)*tree[x].lzy;
tree[rs(x)].lzy+=tree[x].lzy;
tree[x].lzy=0;
}
void change(int x,int l,int r,int k){
if(tree[x].l>=l&&tree[x].r<=r){
tree[x].sq+=2*tree[x].sum*k+(r-l+1)*k*k;
tree[x].sum+=(tree[x].r-tree[x].l+1)*k;
tree[x].lzy+=k;
return;
}
if(tree[x].lzy) push_down(x);
int mid=(tree[x].l+tree[x].r)>>1;
if(r<=mid) change(ls(x),l,r,k);
else if(l>=mid+1) change(rs(x),l,r,k);
else {
change(ls(x),l,mid,k);
change(rs(x),mid+1,r,k);
}
push_up(x);
}
double query_sum(int x,int l,int r){
if(tree[x].l>=l&&tree[x].r<=r){
return tree[x].sum;
}
if(tree[x].lzy) push_down(x);
int mid=(tree[x].l+tree[x].r)>>1;
double res=0;
if(l<=mid) res+=query_sum(ls(x),l,r);
if(r>mid) res+=query_sum(rs(x),l,r);
push_up(x);
return res;
}
double query_sq(int x,int l,int r){
if(tree[x].l>=l&&tree[x].r<=r){
return tree[x].sq;
}
if(tree[x].lzy) push_down(x);
int mid=(tree[x].l+tree[x].r)>>1;
double res=0;
if(l<=mid) res+=query_sq(ls(x),l,r);
if(r>mid) res+=query_sq(rs(x),l,r);
push_up(x);
return res;
}
int main(){
n=read(),m=read();
for(register int i=1;i<=n;i++) scanf("%lf",&a[i]);
build(1,1,n);
while(m--){
int t=read(),x=read(),y=read();
double k;
if(t==1){
scanf("%lf",&k);
change(1,x,y,k);
}
if(t==2){
printf("%.4lf\n",query_sum(1,x,y)/(y-x+1));
}
if(t==3){
double s1=query_sq(1,x,y)/(y-x+1),s2=query_sum(1,x,y)/(y-x+1);
double ans=s1-s2*s2;
printf("%.4lf\n",ans);
}
}
}
线段树不知到哪里出了问题,求调,谢谢