寻找神格

来源:互联网 发布:网络匿名性的缺点 编辑:程序博客网 时间:2024/04/30 04:07

题目大意

给定一个序列要求支持单点修改、区间修改、区间求和、区间求方差。

计算方差

我们来看看如何解决方差。
设sum为平方和,num为和。
s2=1n[(a1numn)2+...(annumn)2]
s2=1n(sum+num2n2num2n)
s2=1n(sumnum2n)
发现方差只与平方和与和有关,因此我们可以开一颗线段树来维护这两个因素。
至于区间修改,同平方和那题。

参考程序

#include<cstdio>#include<iostream>#include<cstdlib>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;typedef long long ll;typedef double db;const ll maxn=100000+10;ll sum[maxn*4],num[maxn*4],add[maxn*4];ll i,j,k,l,t,n,m;db x,y,z,ans;void change(ll p,ll l,ll r,ll a,ll b,ll x){    if (l==a&&r==b){        sum[p]=sum[p]+x*x*(r-l+1)+2*num[p]*x;        num[p]=num[p]+x*(r-l+1);        add[p]=add[p]+x;        return;    }    ll mid=(l+r)/2;    if (add[p]){        sum[p*2]=sum[p*2]+add[p]*add[p]*(mid-l+1)+2*num[p*2]*add[p];        num[p*2]=num[p*2]+add[p]*(mid-l+1);        add[p*2]=add[p*2]+add[p];        sum[p*2+1]=sum[p*2+1]+add[p]*add[p]*(r-mid)+2*num[p*2+1]*add[p];        num[p*2+1]=num[p*2+1]+add[p]*(r-mid);        add[p*2+1]=add[p*2+1]+add[p];        add[p]=0;    }    if (b<=mid) change(p*2,l,mid,a,b,x);    else if (a>mid) change(p*2+1,mid+1,r,a,b,x);    else{        change(p*2,l,mid,a,mid,x);        change(p*2+1,mid+1,r,mid+1,b,x);    }    sum[p]=sum[p*2]+sum[p*2+1];    num[p]=num[p*2]+num[p*2+1];}ll getsum(ll p,ll l,ll r,ll a,ll b){    if (l==a&&r==b) return sum[p];    ll mid=(l+r)/2;    if (add[p]){        sum[p*2]=sum[p*2]+add[p]*add[p]*(mid-l+1)+2*num[p*2]*add[p];        num[p*2]=num[p*2]+add[p]*(mid-l+1);        add[p*2]=add[p*2]+add[p];        sum[p*2+1]=sum[p*2+1]+add[p]*add[p]*(r-mid)+2*num[p*2+1]*add[p];        num[p*2+1]=num[p*2+1]+add[p]*(r-mid);        add[p*2+1]=add[p*2+1]+add[p];        add[p]=0;    }    if (b<=mid) return getsum(p*2,l,mid,a,b);    else if (a>mid) return getsum(p*2+1,mid+1,r,a,b);    else return getsum(p*2,l,mid,a,mid)+getsum(p*2+1,mid+1,r,mid+1,b);}ll getnum(ll p,ll l,ll r,ll a,ll b){    if (l==a&&r==b) return num[p];    ll mid=(l+r)/2;    if (add[p]){        sum[p*2]=sum[p*2]+add[p]*add[p]*(mid-l+1)+2*num[p*2]*add[p];        num[p*2]=num[p*2]+add[p]*(mid-l+1);        add[p*2]=add[p*2]+add[p];        sum[p*2+1]=sum[p*2+1]+add[p]*add[p]*(r-mid)+2*num[p*2+1]*add[p];        num[p*2+1]=num[p*2+1]+add[p]*(r-mid);        add[p*2+1]=add[p*2+1]+add[p];        add[p]=0;    }    if (b<=mid) return getnum(p*2,l,mid,a,b);    else if (a>mid) return getnum(p*2+1,mid+1,r,a,b);    else return getnum(p*2,l,mid,a,mid)+getnum(p*2+1,mid+1,r,mid+1,b);}int main(){    scanf("%lld%lld",&n,&m);    fo(i,1,n){        scanf("%lld",&j);        change(1,1,n,i,i,j);    }    fo(i,1,m){        scanf("%lld",&t);        if (!t){            scanf("%lld%lld",&j,&k);            change(1,1,n,j,j,k);        }        else if (t==1){            scanf("%lld%lld%lld",&j,&k,&l);            change(1,1,n,j,k,l);        }        else if (t==2){            scanf("%lld%lld",&j,&k);            printf("%lld\n",getnum(1,1,n,j,k));        }        else{            scanf("%lld%lld",&j,&k);            l=getnum(1,1,n,j,k);t=getsum(1,1,n,j,k);            x=l;y=t;z=(k-j+1);            ans=(double)y*z;            ans=(double)(ans-(double)x*x);            ans=(double)ans/((double)z*z);            printf("%.4lf\n",ans);//有spj,为了防误差这里保留4位。        }    }    return 0;}
0 0
原创粉丝点击