我推得方差公式是 Σ(i=1,n)ai^2 + 2 * average(a) * sum(a) + n * average(a)^2
按照这个式子写了下线段树维护区间平方和,输出的时候按照上述公式减去Σ外面的项,得到结果,过样例了,但是就是WA,看了题解,也没明白错在哪,求大佬指教
#include <cstdio>
#include <cmath>
#include <cstring>
const int MAXN = 100005;
struct TREE{
double w,f;
double d;
}tree[MAXN*4];
int n,m;
double num[MAXN];
void build(int k,int l,int r){
if(l == r){
tree[k].w = num[l];
tree[k].d = num[l]*num[l];
return;
}
int mid = (l+r)>>1;
build(k<<1,l,mid);
build((k<<1)+1,mid+1,r);
tree[k].w = tree[k<<1].w + tree[(k<<1)+1].w;
tree[k].d = tree[k<<1].d + tree[(k<<1)+1].d;
}
void ad(int k,int l,int r,double v){
tree[k].d += 2*v*tree[k].w + (r-l+1)*v*v;
tree[k].w += (r-l+1)*v;
tree[k].f += v;
}
void pushdown(int k,int l,int r){
if(tree[k].f == 0) return;
int mid = (l+r)>>1;
ad(k<<1,l,mid,tree[k].f);
ad((k<<1)+1,mid+1,r,tree[k].f);
tree[k].f = 0;
}
int gl,gr;
double ret;
void search_average(int k,int l,int r){
if(l > gr || r < gl) return;
if(l >= gl && r <= gr){
ret += tree[k].w;
return;
}
pushdown(k,l,r);
int mid = (l+r)>>1;
search_average(k<<1,l,mid);
search_average((k<<1)+1,mid+1,r);
}
void search_variance(int k,int l,int r){
if(l > gr || r < gl) return;
if(l >= gl && r <= gr){
ret += tree[k].d;
return;
}
pushdown(k,l,r);
int mid = (l+r)>>1;
search_average(k<<1,l,mid);
search_average((k<<1)+1,mid+1,r);
}
double gv;
void alter_section(int k,int l,int r){
if(l > gr || r < gl) return;
if(l >= gl && r <= gr){
ad(k,l,r,gv);
return;
}
//pushdown(k,l,r);
int mid = (l+r)>>1;
alter_section(k<<1,l,mid);
alter_section((k<<1)+1,mid+1,r);
tree[k].w = tree[k<<1].w + tree[(k<<1)+1].w;
tree[k].d = tree[k<<1].d + tree[(k<<1)+1].d;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1; i <= n ; i++){
scanf("%lf",&num[i]);
}
build(1,1,n);
for(int i = 1; i <= m; i ++){
int t;
scanf("%d",&t);
if(t == 1){
scanf("%d%d%lf",&gl,&gr,&gv);
alter_section(1,1,n);
}
else if(t == 2){
scanf("%d%d",&gl,&gr);
ret = 0;
search_average(1,1,n);
printf("%.4lf\n",ret/(gr-gl+1));
}
else if(t == 3){
scanf("%d%d",&gl,&gr);
ret = 0;
search_average(1,1,n);
double sum = ret;
double aver = ret/(gr-gl+1);
ret = 0;
search_variance(1,1,n);
//printf("a^2+b^2+c^2=%.4f\n",ret);
printf("%.4lf\n",(ret-2*aver*sum+(gr-gl+1)*aver*aver)/(gr-gl+1));
}
}
return 0;
}