@xiaoziyao
2020-10-19T08:29:12.000000Z
字数 1556
阅读 1780
解题报告
CF319C Kalila and Dimna in the Logging Industry解题报告:
很显然,我们第一次砍的一定是第一棵树,且砍倒最后一棵树以后就不需要任何费用了,这样,题意就转化为如何花费最小的费用砍倒第棵树。
有一个很显然的贪心思想,我们砍树一定从前往后砍(中间可以跳过一些树),因为我们砍这棵树一定无法更新砍树的费用。
设为砍倒第棵树的费用,那么可以列出转移方程。
这个一定无法通过题目,因此需要优化。
考虑斜率优化:设两个的决策点满足,且比更优,那么有:
变一下形式:。
化成斜率式之后,由于是递增的,因此用单调队列维护一个上凸壳就好了。
时间复杂度:。
记得开,开大一点。
#include<stdio.h>#include<string.h>#define int long long#define inf 1000000000000000000const int maxn=100005;int n,l,r;int a[maxn],b[maxn],f[maxn],q[maxn];inline int min(int a,int b){return a<b? a:b;}inline int x(int p){return b[p];}inline int y(int p){return f[p];}inline double slope(int a,int b){if(x(a)==x(b))return y(a)>y(b)? inf:-inf;return 1.0*(y(a)-y(b))/(x(a)-x(b));}signed main(){scanf("%lld",&n);for(int i=1;i<=n;i++)scanf("%lld",&a[i]);for(int i=1;i<=n;i++)scanf("%lld",&b[i]);for(int i=1;i<=n;i++)f[i]=inf;f[1]=b[1],q[++r]=0;for(int i=1;i<=n;i++){while(l<r&&slope(q[l+1],q[l])>=-a[i])l++;f[i]=f[q[l]]+b[q[l]]*a[i];while(l<r&&slope(q[r-1],i)>=slope(q[r],q[r-1]))r--;q[++r]=i;}printf("%lld\n",f[n]);return 0;}
