这道题一眼线段树
然而并不太好想怎么维护😭
图片引用自luogu@远航之曲

总体思路就是记录区间和,还有区间的平方和,通过图2来进行平方和的标记下传,用图一的式子来算出方差

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
#include<string>
#include<stack>
#include<set>
using namespace std;
inline int read(){
    int x=0;
    char c=getchar();
    bool flag=0;
    while(c<'0'||c>'9'){
		if(c=='-')
			flag=1;
		c=getchar();
	}
    while(c>='0'&&c<='9'){
		x=(x<<3)+(x<<1)+c-'0';
		c=getchar();
	}
    return flag?-x:x;
}
double tree1[500100];
double tree2[500100];
double lazy[500100],a[500010];
void build(int l,int r,int t){
	if(l==r){
		tree1[t]=a[l];
		tree2[t]=a[l]*a[l];
		return;
	}
	int mid=(l+r)/2;
	build(l,mid,t*2);
	build(mid+1,r,t*2+1);
	tree1[t]=tree1[t*2]+tree1[t*2+1];
	tree2[t]=tree2[t*2]+tree2[t*2+1];
}
void push(int t,int len){
	if(lazy[t]==0)return;
	tree2[t*2]+=(len-len/2)*lazy[t]*lazy[t]+2*tree1[t*2]*lazy[t];
	tree2[t*2+1]+=(len/2)*lazy[t]*lazy[t]+2*tree1[t*2+1]*lazy[t];
	tree1[t*2]+=(len-len/2)*lazy[t];
	tree1[t*2+1]+=(len/2)*lazy[t];
	lazy[t*2]+=lazy[t];
	lazy[t*2+1]+=lazy[t];
	lazy[t]=0;
	return;
}
double ans;
void query(int ll,int rr,int l,int r,int t,int flag){
	if(ll<=l&&r<=rr){
		if(flag==1)ans+=tree1[t];
		else ans+=tree2[t]; 
		return;
	}
	push(t,r-l+1);
	int mid=(l+r)/2;
	if(ll<=mid)query(ll,rr,l,mid,t*2,flag);
	if(rr>mid)query(ll,rr,mid+1,r,t*2+1,flag);
	tree1[t]=tree1[t*2]+tree1[t*2+1];
	tree2[t]=tree2[t*2]+tree2[t*2+1];
}
void modify(int ll,int rr,int l,int r,double c,int t){
	if(ll<=l&&r<=rr){
		lazy[t]+=c;
		tree2[t]+=2*c*tree1[t]+c*c*(r-l+1);
		tree1[t]+=(r-l+1)*c;
		return;
	}
	push(t,r-l+1);
	int mid=(l+r)/2;
	if(ll<=mid)modify(ll,rr,l,mid,c,t*2);
	if(rr>mid)modify(ll,rr,mid+1,r,c,t*2+1);
	tree1[t]=tree1[t*2]+tree1[t*2+1];
	tree2[t]=tree2[t*2]+tree2[t*2+1];
}
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>a[i];
	build(1,n,1);
	while(m--){
		int opt;
		cin>>opt;
		if(opt==1){
			int a,b;
			double c;
			cin>>a>>b>>c;
			modify(a,b,1,n,c,1);
		}else if(opt==2){
			int a,b;
			cin>>a>>b;
			ans=0;
			query(a,b,1,n,1,1);
			double avg=ans;
			avg=avg/(b-a+1);
			printf("%.4lf\n",avg);
		}else if(opt==3){
			int a,b;
			cin>>a>>b;
			ans=0;
			query(a,b,1,n,1,1);
			double avg=ans;
			avg=avg/(b-a+1);
			ans=0;
			query(a,b,1,n,1,2);
			double sum=ans;
			sum=sum/(b-a+1);
			double ANS=sum-avg*avg;
			printf("%.4lf\n",ANS); 
		}
	}
	return 0;
}