[关闭]
@xiaoziyao 2020-10-19T08:29:12.000000Z 字数 1556 阅读 961

CF319C Kalila and Dimna in the Logging Industry解题报告

解题报告


CF319C Kalila and Dimna in the Logging Industry解题报告:

更好的阅读体验

题意

分析

很显然,我们第一次砍的一定是第一棵树,且砍倒最后一棵树以后就不需要任何费用了,这样,题意就转化为如何花费最小的费用砍倒第棵树。

有一个很显然的贪心思想,我们砍树一定从前往后砍(中间可以跳过一些树),因为我们砍这棵树一定无法更新砍树的费用。

为砍倒第棵树的费用,那么可以列出转移方程

这个一定无法通过题目,因此需要优化。

考虑斜率优化:设两个的决策点满足,且更优,那么有:

变一下形式:

化成斜率式之后,由于是递增的,因此用单调队列维护一个上凸壳就好了。

时间复杂度:

代码

记得开开大一点。

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