[关闭]
@xiaoziyao 2020-09-07T15:41:24.000000Z 字数 2488 阅读 1010

CF643C Levels and Regions解题报告

解题报告


CF643C Levels and Regions解题报告:

更好的阅读体验

题意

分析

比较好的dp题,把期望和斜率优化结合起来了。

首先,既然小时通过关卡的概率为,那么关卡期望个小时通过,设的前缀和,那么关卡期望个小时通过。

然后,对于每一段,它的期望为

这里为了方便,我们把这一段改为,即。这样它的期望就是

我们设的前缀和;的前缀和。

这一段的期望可以直接改为

然后开始dp,我们设为从关卡处理到关卡,分段的最小期望。

那么很显然有转移:

看到这个式子存在项,果断选择斜率优化。

设当时处理到段,且存在两个的决策点满足,且优,那么有:

然后拆括号,移项:

因为,所以,所以可以两边同除,不变号:

看成坐标,把看成坐标,这就是一个斜率的形式,直接上斜率优化板子就好了。

注意,因为这里是小于号,综合分析后应该取下凸壳。

时间复杂度:,可以通过本题。

代码

  1. #include<stdio.h>
  2. #include<queue>
  3. #define int long long
  4. #define inf 10000000000000000
  5. using namespace std;
  6. const int maxn=200005,maxm=55;
  7. int i,j,k,m,n,l,r;
  8. int a[maxn],suma[maxn],q[maxn];
  9. double b[maxn],c[maxn],sumb[maxn],sumc[maxn],f[maxm][maxn];
  10. inline int x(int p){
  11. return suma[p];
  12. }
  13. inline double y(int p,int c){
  14. return f[c-1][p]+1.0*suma[p]*sumb[p]-sumc[p];
  15. }
  16. inline double slope(int a,int b,int c){
  17. if(x(a)==x(b))
  18. return y(a,c)>y(b,c)? inf:-inf;
  19. return 1.0*(y(a,c)-y(b,c))/(x(a)-x(b));
  20. }
  21. signed main(){
  22. scanf("%lld%lld",&n,&m);
  23. for(i=1;i<=n;i++){
  24. scanf("%lld",&a[i]);
  25. suma[i]=suma[i-1]+a[i];
  26. b[i]=1.0/a[i],sumb[i]=sumb[i-1]+b[i];
  27. c[i]=1.0*suma[i]/a[i],sumc[i]=sumc[i-1]+c[i];
  28. }
  29. for(i=1;i<=n;i++)
  30. f[0][i]=inf;
  31. for(i=1;i<=m;i++){
  32. l=1,r=0;
  33. q[++r]=0;
  34. for(j=1;j<=n;j++){
  35. while(l<r&&slope(q[l+1],q[l],i)<=sumb[j])
  36. l++;
  37. f[i][j]=f[i-1][q[l]]+sumc[j]-sumc[q[l]]-suma[q[l]]*(sumb[j]-sumb[q[l]]);
  38. while(l<r&&slope(j,q[r-1],i)<=slope(q[r],q[r-1],i))
  39. r--;
  40. q[++r]=j;
  41. }
  42. }
  43. printf("%.10lf\n",f[m][n]);
  44. return 0;
  45. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注