【JZOJ4585】Robert 的军队

来源:互联网 发布:视频监控软件破解版 编辑:程序博客网 时间:2024/06/11 09:54

Description

这里写图片描述

Solution

一开始以为这题是什么二分,数据结构之类的,结果推不出来。
后来推了大半天,才发现了用平方和和平均数来快速求方差,但是只把O(n3)化为了O(n2)
没办法水了水,打了一个分段贪心,因为在对拍的时候发现选的数都只有l个。然后就变为O(n)了。结果,这种贪心是可以证明的,不过博主有点懒,不想打。

注意

这道题每个数的范围开的有点大,平方和会爆0x7fffffff(maxlongint),所以ans要开大一点。

注意c++的运算规律

比如说a=b*c,b*c会爆int,那么b和c都必须要开long long,除法类似。

Code

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=100007;long long i,j,k,l,t,n,m,r;double ans,ave,pp;long long a[maxn];double sum[maxn],ans2;double ping[maxn];bool cmp(long long x,long long y){return x<y;}int main(){    freopen("army.in","r",stdin);    freopen("army.out","w",stdout);    scanf("%lld%lld%lld",&n,&l,&r);    fo(i,1,n)scanf("%lld",&a[i]);    sort(a+1,a+1+n,cmp);    fo(i,1,n)ping[i]=a[i]*a[i]+ping[i-1],sum[i]+=sum[i-1]+a[i];ans=1000000000000000000;    if(n<=2000){        fo(i,1,n){            fo(j,l,r){                k=i+j-1;if(k>n)break;                ave=sum[k]-sum[i-1];ave=ave/j;                pp=ping[k]-ping[i-1];pp=pp/j-ave*ave;                if(pp<ans){                    ans=pp;                }            }        }    }    else{        fo(i,1,n){            k=i+l-1;if(k>n)break;            ave=sum[k]-sum[i-1];ave=ave/l;            pp=ping[k]-ping[i-1];pp=pp/l-ave*ave;            if(pp<ans){                ans=pp;            }        }        }    printf("%.3f\n",ans);}
1 0
原创粉丝点击