方差拆开
线段树维护区间和 , 区间平方和 , 修改时平方差一下就可以了
#include<bits/stdc++.h>
#define N 100050
#define len(x) (t[x].r-t[x].l+1)
using namespace std;
struct Node{int l,r; double v1,v2,tag;}t[N<<2];
int n,m; double a[N];
void Pushup(int x){
t[x].v1 = t[x<<1].v1 + t[x<<1|1].v1;
t[x].v2 = t[x<<1].v2 + t[x<<1|1].v2;
}
void build(int x,int l,int r){
t[x].l = l , t[x].r = r;
if(l==r){t[x].v1=a[l]; t[x].v2=a[l]*a[l]; return;}
int mid = (l+r) >> 1;
build(x<<1,l,mid); build(x<<1|1,mid+1,r);
Pushup(x);
}
void Pushdown(int x){
if(t[x].tag){
t[x<<1].v2 += 2 * t[x<<1].v1 * t[x].tag;
t[x<<1].v2 += t[x].tag * t[x].tag * len(x<<1);
t[x<<1|1].v2 += 2 * t[x<<1|1].v1 * t[x].tag;
t[x<<1|1].v2 += t[x].tag * t[x].tag * len(x<<1|1);
t[x<<1].v1 += t[x].tag * len(x<<1);
t[x<<1|1].v1 += t[x].tag * len(x<<1|1);
t[x<<1].tag += t[x].tag;
t[x<<1|1].tag += t[x].tag;
t[x].tag = 0;
}
}
void Update(int x,int L,int R,double val){
if(L<=t[x].l && t[x].r<=R){
t[x].v2 += 2 * t[x].v1 * val;
t[x].v2 += val * val * len(x);
t[x].v1 += val * len(x);
t[x].tag += val;
return;
}
Pushdown(x);
int mid = (t[x].l+t[x].r) >> 1;
if(L<=mid) Update(x<<1,L,R,val);
if(R>mid) Update(x<<1|1,L,R,val);
Pushup(x);
}
double Quary(int x,int L,int R,int type){
if(L<=t[x].l && t[x].r<=R){
if(type==1) return t[x].v1;
else return t[x].v2;
}
Pushdown(x);
int mid = (t[x].l+t[x].r) >> 1; double ans=0;
if(L<=mid) ans += Quary(x<<1,L,R,type);
if(R>mid) ans += Quary(x<<1|1,L,R,type);
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%lf",&a[i]);
build(1,1,n);
for(int i=1;i<=m;i++){
int op,x,y; scanf("%d%d%d",&op,&x,&y);
if(op==1){
double k; scanf("%lf",&k);
Update(1,x,y,k);
}
if(op==2){
double Sum=Quary(1,x,y,1);
double len = (y-x+1) * 1.0;
printf("%0.4lf\n",Sum/len);
}
if(op==3){
double Sum = Quary(1,x,y,1);
double Sum2 = Quary(1,x,y,2);
double len = (y-x+1) * 1.0;
double ans = Sum2 / len - (Sum/len * Sum/len);
printf("%0.4lf\n",ans);
}
} return 0;
}