@xiaoziyao
2020-10-19T16:29:12.000000Z
字数 1556
阅读 1128
解题报告
CF319C Kalila and Dimna in the Logging Industry解题报告:
很显然,我们第一次砍的一定是第一棵树,且砍倒最后一棵树以后就不需要任何费用了,这样,题意就转化为如何花费最小的费用砍倒第棵树。
有一个很显然的贪心思想,我们砍树一定从前往后砍(中间可以跳过一些树),因为我们砍这棵树一定无法更新砍树的费用。
设为砍倒第棵树的费用,那么可以列出转移方程。
这个一定无法通过题目,因此需要优化。
考虑斜率优化:设两个的决策点满足,且比更优,那么有:
变一下形式:。
化成斜率式之后,由于是递增的,因此用单调队列维护一个上凸壳就好了。
时间复杂度:。
记得开,开大一点。
#include<stdio.h>
#include<string.h>
#define int long long
#define inf 1000000000000000000
const 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;
}