bzoj4518 [Sdoi2016]征途

网友投稿 571 2022-08-29

bzoj4518 [Sdoi2016]征途

bzoj4518 [Sdoi2016]征途

(​​ Description Pine开始了从S地到T地的征途。 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站。 Pine计划用m天到达T地。除第m天外,每一天晚上Pine都必须在休息站过夜。所以,一段路必须在同一天中走完。 Pine希望每一天走的路长度尽可能相近,所以他希望每一天走的路的长度的方差尽可能小。 帮助Pine求出最小方差是多少。 设方差是v,可以证明,v×m^2是一个整数。为了避免精度误差,输出结果时输出v×m^2。

Input 第一行两个数 n、m。 第二行 n 个数,表示 n 段路的长度

Output 一个数,最小方差乘以 m^2 后的值

Sample Input 5 2

1 2 5 8 6 Sample Output 36 HINT

1≤n≤3000,保证从 S 到 T 的总路程不超过 30000

Source 鸣谢Menci上传 怎么搞 首先需要对方差的公式进行一次化简 具体的参展物 参考“百度”我试过 没问题可以展开 设dp[i][k]表示我1~i段路程被我分成了k段 那么现在我们有了一种o(n^3)的做法 显然不够优秀 怎么办 这时候我们需要好好考虑方差的那个式子 s2=∑i=1n(x[i]−x¯)2我们现在再考虑题目为什么要∗m2因为乘完之后我可以展开化简怎么搞这就变成了s2=m∗∑i=1nx[i]2−sum[i]2那么因为m是常数项可以忽略后面再去做它 所以我们可以将前半部分看作是 将1~i划分成j段并且 他们平常的和最小 那么显然可以斜率优化了 时间复杂度o(n^2) 注意边界 如:切1刀的时候要单独处理 注意 因为我枚举了切刀 所以我每次做应该至少从满足我切刀的位置去处理

#include#define ll long long#define N 3300inline char gc(){ static char now[1<<16],*S,*T; if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;} return *S++;}inline int read(){ int x=0;char ch=gc(); while(ch<'0'||ch>'9') ch=gc(); while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc(); return x;}int a[N],n,m,q[N],pre,now;ll sum[N],f[2][N];inline double slope(int j1,int j2){ return (double)(f[pre][j1]-f[pre][j2]+sum[j1]*sum[j1]-sum[j2]*sum[j2])*0.5/(sum[j1]-sum[j2]);}int main(){ //freopen("bzoj4518.in","r",stdin); n=read();m=read();pre=0,now=1; for (int i=1;i<=n;++i) a[i]=read(),sum[i]=sum[i-1]+a[i]; for (int i=1;i<=n;++i) f[pre][i]=sum[i]*sum[i]; for (int j=2;j<=m;++j){ int l=1,r=0;q[++r]=j-1; for (int i=j;i<=n;++i){ while(lslope(q[r],i)) --r;q[++r]=i; }now^=1;pre^=1; } printf("%lld\n",f[pre][n]*m-sum[n]*sum[n]); return 0;}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Loj 6001「网络流 24 题」太空飞行计划
下一篇:挺带劲,这款国人开源的监控系统真强大~(视频监控系统开源)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~