方差
链接:https://www.luogu.org/problemnew/show/P1471
题解:
对式子进行一些化简就会发现等价于在求方差
裸的线段树
#include <bits/stdc++.h>
using namespace std;
#define maxn 111111
#define mid (p[x].h+p[x].t)/2
int n,m;
double a[maxn],b[maxn];
struct re
{
int h,t;
double x1,x2,lazy;
}p[maxn*4];
void updata(int x)
{
p[x].x1=p[x*2].x1+p[x*2+1].x1;
p[x].x2=p[x*2].x2+p[x*2+1].x2;
}
void build(int x,int h,int t)
{
p[x].h=h; p[x].t=t;
if (h==t)
{
p[x].x1=a[h]; p[x].x2=b[h];
return;
}
build(x*2,h,mid); build(x*2+1,mid+1,t);
updata(x);
}
void down(int x)
{
if (p[x].lazy)
{
p[x].x2+=2*p[x].x1*p[x].lazy+(p[x].t-p[x].h+1)*p[x].lazy*p[x].lazy;
p[x].x1+=(p[x].t-p[x].h+1)*p[x].lazy;
if (p[x].h!=p[x].t)
{
p[x*2].lazy+=p[x].lazy;
p[x*2+1].lazy+=p[x].lazy;
}
p[x].lazy=0;
}
}
void change(int x,int h,int t,double sum)
{
down(x);
if (p[x].h>t||p[x].t<h) return;
if (h<=p[x].h&&p[x].t<=t)
{
p[x].lazy+=sum; down(x);
return;
}
change(x*2,h,t,sum); change(x*2+1,h,t,sum);
updata(x);
}
double query1(int x,int h,int t)
{
down(x);
if (p[x].h>t||p[x].t<h) return(0);
if (h<=p[x].h&&p[x].t<=t)
{
return(p[x].x1);
}
return(query1(x*2,h,t)+query1(x*2+1,h,t));
}
double query2(int x,int h,int t)
{
down(x);
if (p[x].h>t||p[x].t<h) return(0);
if (h<=p[x].h&&p[x].t<=t)
{
return(p[x].x2);
}
return(query2(x*2,h,t)+query2(x*2+1,h,t));
}
int main()
{
std::ios::sync_with_stdio(false);
cin>>n>>m;
for (int i=1;i<=n;i++)
{
cin>>a[i]; b[i]=(a[i]*a[i]);
}
build(1,1,n);
for (int i=1;i<=m;i++)
{
int c,d,e; double f;
cin>>c;
if (c==1)
{
cin>>d>>e>>f;
change(1,d,e,f);
}
if (c==2)
{
cin>>d>>e;
printf("%.4f\n",query1(1,d,e)/(e-d+1));
}
if (c==3)
{
cin>>d>>e;
double x=query1(1,d,e),y=x/(e-d+1);
printf("%.4f\n",(query2(1,d,e)-2*y*x)/(e-d+1)+y*y);
}
}
}