[noi模拟赛]math (斜率优化,未测)

来源:互联网 发布:大数据应用系统架构 编辑:程序博客网 时间:2024/06/05 11:30

拖了许久的坑。。
sum[i]=t=1ia[t]
sum1[i]=t=1i1a[t]
sum2[i]=t=1isum[t]a[t]
f[i][k]前i个数,分成k部分的最小得分。
f[i][k]=min{f[j][k-1]+sum2[i]-sum2[j]-sum[j]*(sum1[i]-sum1[j]|k-1<=j< i)标准的2d/1d方程,进行斜率优化,设k1< k2,k1优于k2,则见代码。。还是维护下凸曲线。。然后这题精度有毒。也不知道能不能过。。。

#include <cstdio>#include <cstring>#define N 200010#define ll long longint n,k,a[N],p=0,q[N],h=0,t=1;ll sum[N];double sum1[N],sum2[N],f[2][N];inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}inline double slope(int k1,int k2){    return (f[p][k2]-f[p][k1]+sum2[k1]-sum2[k2]+sum[k2]*sum1[k2]-sum[k1]*sum1[k1])/(sum[k2]-sum[k1]);}int main(){    freopen("math.in","r",stdin);    freopen("math.out","w",stdout);    n=read();k=read();    for(int i=1;i<=n;++i) a[i]=read(),sum[i]=sum[i-1]+a[i];    for(int i=1;i<=n;++i){        sum1[i]=sum1[i-1]+1.0/a[i];        sum2[i]=sum2[i-1]+sum[i]*1.0/a[i];    }    for(int i=1;i<=n;++i) f[p][i]=sum2[i];    for(int x=2;x<=k;++x){        h=0,t=1;q[++h]=x-1;        for(int i=x;i<=n;++i){            while(h<t&&slope(q[h],q[h+1])<sum1[i]) ++h;            f[p^1][i]=f[p][q[h]]+sum2[i]-sum2[q[h]]-sum[q[h]]*(sum1[i]-sum1[q[h]]);            while(h<t&&slope(q[t],i)<slope(q[t-1],q[t])) --t;            q[++t]=i;        }p^=1;    }    printf("%.15lf\n",f[p][n]);    return 0;}
原创粉丝点击