样例过了全WA
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=4e5+10;
int n,m;
double a[maxn];
struct Tree{ //线段树维护:和,平方和
int left,right;
double tag1,tag2,sum1,sum2; //tag1是和的懒标记,sum1是和;tag2是平方和的懒标记,sum2是平方和
}tree[maxm];
inline void maketag(int root,double k1,double k2,int l,int r){
tree[root].tag1+=k1;
tree[root].tag2+=k2;
tree[root].sum2+=(r-l+1)*k2+2*tree[root].sum1*k1;
tree[root].sum1+=(r-l+1)*k1;
}
inline void pushdown(int root){
if(tree[root].left!=tree[root].right){
int mid=(tree[root].left+tree[root].right)>>1;
maketag(root<<1,tree[root].tag1,tree[root].tag2,tree[root].left,mid);
maketag(root<<1|1,tree[root].tag1,tree[root].tag2,mid+1,tree[root].right);
tree[root].tag1=0;
tree[root].tag2=0;
}
return;
}
inline void build(int root,int l,int r){
// cout<<root<<" "<<l<<" "<<r<<"\n";
tree[root].left=l;
tree[root].right=r;
if(tree[root].left==tree[root].right){
tree[root].sum1=a[tree[root].left];
tree[root].sum2=a[tree[root].left]*a[tree[root].left];
return;
}
int mid=(tree[root].left+tree[root].right)>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
tree[root].sum1=tree[root<<1].sum1+tree[root<<1|1].sum1;
tree[root].sum2=tree[root<<1].sum2+tree[root<<1|1].sum2;
}
inline void update(int root,int l,int r,double k){
pushdown(root);
if(l<=tree[root].left&&r>=tree[root].right){
maketag(root,k,k*k,tree[root].left,tree[root].right);
return;
}
int mid=(tree[root].left+tree[root].right)>>1;
if(l<=mid) update(root<<1,l,r,k);
if(r>mid) update(root<<1|1,l,r,k);
tree[root].sum1=tree[root<<1].sum1+tree[root<<1|1].sum1;
tree[root].sum2=tree[root<<1].sum2+tree[root<<1|1].sum2;
}
inline double query1(int root,int l,int r){
pushdown(root);
if(l<=tree[root].left&&r>=tree[root].right){
return tree[root].sum1;
}
double res=0;
int mid=(tree[root].left+tree[root].right)>>1;
if(l<=mid) res+=query1(root<<1,l,r);
if(r>mid) res+=query1(root<<1|1,l,r);
return res;
}
inline double query2(int root,int l,int r){
pushdown(root);
if(l<=tree[root].left&&r>=tree[root].right){
return tree[root].sum2;
}
double res=0;
int mid=(tree[root].left+tree[root].right)>>1;
if(l<=mid) res+=query2(root<<1,l,r);
if(r>mid) res+=query2(root<<1|1,l,r);
return res;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lf",&a[i]);
}
build(1,1,n);
while(m--){
int op;
scanf("%d",&op);
if(op==1){
int x,y;
double k;
scanf("%d%d%lf",&x,&y,&k);
update(1,x,y,k);
}
if(op==2){
int x,y;
scanf("%d%d",&x,&y);
printf("%.4lf\n",1.0*query1(1,x,y)/(y-x+1));
}
if(op==3){
int x,y;
scanf("%d%d",&x,&y);
double sum=query1(1,x,y);
double ave=1.0*sum/(y-x+1);
double pow_sum=query2(1,x,y);
// cout<<pow_sum<<" "<<sum<<" "<<ave<<"\n";
printf("%.4lf\n",1.0*(pow_sum-2.0*ave*sum+ave*ave*(y-x+1))/(y-x+1));
}
}
return 0;
}