【五校联考4day1】寻找神格
这题t<=2的都可以很容易地更改或是查询,重点就是求方差了。
题目已经给了方差的求法,我们只需要将其化简即可。(手推就行了)
最后化简成:
A和B之间的:
sum(a[i]^2)/(B-A+1)-sum(a[i])*sum(a[i])/(B-A+1)/(B-A+1)
sum指的是A到B的区间和(a[i]^2为平方和,a[i]为和)
最后构造两个线段树,一个存平方和,一个存和即可。在线的
上标:
#include<cstdio>
#include<algorithm>
#define db double
#define ll long long
using namespace std;
int n,q,tt,A,B,C;
ll lazy[600010],t[600010],tf[600010];
db ans=0;
void update(int x,int l,int r)
{
if (!lazy[x]) return;
tf[x]+=(ll)2*t[x]*lazy[x]+(ll)(r-l+1)*lazy[x]*lazy[x];
t[x]+=(ll)(r-l+1)*lazy[x];
if (l<r) lazy[x<<1]+=lazy[x],lazy[x<<1|1]+=lazy[x];
lazy[x]=0;
}
void inser(int x,int l,int r,int fl,int fr,int ins)
{
update(x,l,r);
if (l==fl && r==fr) {lazy[x]+=ins,update(x,l,r); return;}
int mid=l+r>>1;
if (fr<=mid) inser(x<<1,l,mid,fl,fr,ins);
else if (fl>mid) inser(x<<1|1,mid+1,r,fl,fr,ins);
else inser(x<<1,l,mid,fl,mid,ins),inser(x<<1|1,mid+1,r,mid+1,fr,ins);
update(x<<1,l,mid),update(x<<1|1,mid+1,r);
t[x]=t[x<<1]+t[x<<1|1];
tf[x]=tf[x<<1]+tf[x<<1|1];
}
ll gsum(int x,int l,int r,int fl,int fr)
{
update(x,l,r);
if (l==fl && r==fr) return t[x];
int mid=l+r>>1;
if (fr<=mid) return gsum(x<<1,l,mid,fl,fr);
else if (fl>mid) return gsum(x<<1|1,mid+1,r,fl,fr);
else return gsum(x<<1,l,mid,fl,mid)+gsum(x<<1|1,mid+1,r,mid+1,fr);
}
ll gfs(int x,int l,int r,int fl,int fr)
{
update(x,l,r);
if (l==fl && r==fr) return tf[x];
int mid=l+r>>1;
if (fr<=mid) return gfs(x<<1,l,mid,fl,fr);
else if (fl>mid) return gfs(x<<1|1,mid+1,r,fl,fr);
else return gfs(x<<1,l,mid,fl,mid)+gfs(x<<1|1,mid+1,r,mid+1,fr);
}
int main()
{
freopen("sg.in","r",stdin);
freopen("sg.out","w",stdout);
// 方差=sum(a[i]^2)/n-sum(a[i])^2/n^2
scanf("%d%d\n",&n,&q);
for (int i=1,x;i<=n;i++)
scanf("%d",&x),inser(1,1,n,i,i,x);
while (q--)
{
scanf("%d",&tt);
if (tt==0)
{
scanf("%d%d",&A,&B);
inser(1,1,n,A,A,B);
}
else if (tt==1)
{
scanf("%d%d%d",&A,&B,&C);
inser(1,1,n,A,B,C);
}
else if (tt==2)
{
scanf("%d%d",&A,&B);
printf("%lld\n",gsum(1,1,n,A,B));
}
else if (tt==3)
{
scanf("%d%d",&A,&B);
ans=gsum(1,1,n,A,B);
ans=(db)gfs(1,1,n,A,B)/(B-A+1)-ans*ans/(B-A+1)/(B-A+1);
printf("%.10lf\n",ans);
}
}
return 0;
}
转载需注明出处。