#10192. 「一本通 5.6 练习 5」锯木厂选址
这题斜率优化。详见标。
上标:
#include<cstdio>
#define N 200010
#define db double
#define ll long long
using namespace std;
int n,l=0,len=0,g[N];
ll d[N],sw[N],sd[N],c[N],f[N],ans=(ll)(1<<30)*(1<<30);
inline int read()
{
int x=0; char c=getchar();
while (c<'0' || c>'9') c=getchar();
while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x;
}
ll min(ll x,ll y) {return x<y ? x:y;}
db solve(int x,int y) {return (db)(sw[x]*sd[x]-sw[y]*sd[y])/(sw[x]-sw[y]);}
int main()
{
freopen("#10192.in","r",stdin);
freopen("#10192.out","w",stdout);
n=read();
for (int i=1;i<=n;i++)
{
sw[i]=sw[i-1]+read(),d[i]=read();
sd[i]=sd[i-1]+d[i-1];
c[i]=c[i-1]+sw[i-1]*d[i-1];
}
sw[n+1]=sw[n],sd[n+1]=sd[n]+d[n];
c[n+1]=c[n]+sw[n]*d[n];
for (int i=1;i<=n;i++)
{
while (l<len && solve(g[l+1],g[l])<sd[i]) l++;
ans=min(ans,c[n+1]-sw[g[l]]*(sd[i]-sd[g[l]])-sw[i]*(sd[n+1]-sd[i]));
while (l<len && solve(g[len],g[len-1])>solve(i,g[len])) len--;
g[++len]=i;
}
printf("%lld\n",ans);
return 0;
}
转载需注明出处。