运用一点初中知识可以知道
维护一下区间平方和和区间和就可以处理了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int f;
int x,y;
double k;
struct p{
double sum;
double sqr;
}po[400005];
double lazy[400005];
void pushdown(int ro,int l,int r){
if(lazy[ro]){
int mid=(l+r)>>1;
double k=lazy[ro];lazy[ro]=0;
lazy[ro<<1]+=k;lazy[ro<<1|1]+=k;
po[ro<<1].sqr=po[ro<<1].sqr+2*k*po[ro<<1].sum+k*k*(mid-l+1);
po[ro<<1].sum+=k*(mid-l+1);
po[ro<<1|1].sqr=po[ro<<1|1].sqr+2*k*po[ro<<1|1].sum+k*k*(r-mid);
po[ro<<1|1].sum+=k*(r-mid);
}
}
void pushup(int r){
po[r].sqr=po[r<<1].sqr+po[r<<1|1].sqr;
po[r].sum=po[r<<1].sum+po[r<<1|1].sum;
}
void add(int ro,int l,int r,int L,int R,double k){
if(L<=l&&r<=R){
po[ro].sqr=po[ro].sqr+2*k*po[ro].sum+k*k*(r-l+1);
po[ro].sum+=k*(r-l+1);
lazy[ro]+=k;
return ;
}
pushdown(ro,l,r);
int mid=(r+l)>>1;
if(L<=mid) add(ro<<1,l,mid,L,R,k);
if(R>mid) add(ro<<1|1,mid+1,r,L,R,k);
pushup(ro);
}
double qsum(int ro,int l,int r,int L,int R){
if(L<=l&&r<=R){
return po[ro].sum;
}
pushdown(ro,l,r);
int mid=(l+r)>>1;
double ans=0;
if(L<=mid) ans+=qsum(ro<<1,l,mid,L,R);
if(R>mid) ans+=qsum(ro<<1|1,mid+1,r,L,R);
return ans;
}
double qsqr(int ro,int l,int r,int L,int R){
if(L<=l&&r<=R){
return po[ro].sqr;
}
pushdown(ro,l,r);
int mid=(l+r)>>1;
double ans=0;
if(L<=mid) ans+=qsqr(ro<<1,l,mid,L,R);
if(R>mid) ans+=qsqr(ro<<1|1,mid+1,r,L,R);
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
scanf("%lf",&k);
add(1,1,n,i,i,k);
}
for(int i=1;i<=m;++i){
scanf("%d",&f);
if(f==1){
scanf("%d%d%lf",&x,&y,&k);
add(1,1,n,x,y,k);
}
if(f==2){
scanf("%d%d",&x,&y);
double su=qsum(1,1,n,x,y);
//cout<<qsum(1,1,n,x,y)<<endl;
//cout<<su<<endl;
printf("%.4lf\n",(double)su/(y-x+1));
}
if(f==3){
scanf("%d%d",&x,&y);
double su=qsum(1,1,n,x,y);
double sq=qsqr(1,1,n,x,y);
printf("%.4lf\n",(double)sq/(y-x+1)-su*su/(double)(y-x+1)/(double)(y-x+1));
}
}
return 0;
}