#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;
}
posted @ 2019-02-12 22:06  jz929  阅读(159)  评论(0编辑  收藏  举报