斜率dp的模板总结

#include<cstdio>
#include<algorithm>
using namespace std;
long long sumt[40005],sum[40005],f[40005],q[40005];
double X(long long x)
{
	return sumt[x];
} 
double Y(long long x)
{
	return (f[x]+sum[x]);
}
double slope(long long a,long long b)
{
	return ((Y(a)-Y(b))/(X(a)-X(b)));
}
struct ben
{
	long long t,r;
}a[40005],b[40005];
long long cmp(const ben &a,const ben &b)
{
	return a.t>b.t;
}
int main()
{
	freopen("nt2011_design.in","r",stdin);
	freopen("nt2011_design.out","w",stdout); 
	long long l=0,r=0;
	long long n,m;
	scanf("%lld%lld",&n,&m);
	for(long long i=1;i<=n;i++)
	{
		scanf("%lld%lld",&a[i].t,&a[i].r);
	}
	sort(a+1,a+n+1,cmp);
	for(long long i=1;i<=n;i++)
	{
		if(a[i].t==a[i+1].t)
		{
			a[i+1].r+=a[i].r;
			a[i].r=0;
		}
	}
	long long cnt=0;
	for(long long i=1;i<=n;i++)
	{
		if(a[i].r!=0)
		{
			b[++cnt]=a[i];
		}
	}
	long long maxt=b[1].t;
	b[cnt+1].t=0;
	b[cnt+1].r=0;
	cnt++;
	for(long long i=1;i<=cnt;i++)
	{
		b[i].t=maxt-b[i].t;
		sumt[i]=sumt[i-1]+b[i].r;
		sum[i]=sum[i-1]+b[i].t*b[i].r;
	}
	for(long long i=1;i<=cnt;i++)
	{
		while(l<r&&slope(q[l+1],q[l])<b[i].t)l++;
		f[i]=f[q[l]]+b[i].t*(sumt[i]-sumt[q[l]])-(sum[i]-sum[q[l]]);
		if(i!=cnt)f[i]+=m;
		while(l<r&&slope(i,q[r-1])<slope(q[r-1],q[r]))r--;
		q[++r]=i;
	}
	printf("%lld\n",f[cnt]);
	return 0; 
}
posted @ 2019-08-11 08:53  ShineEternal  阅读(215)  评论(1编辑  收藏  举报