[CF1083]The Fair Nut and Rectangles

The Fair Nut and Rectangles

题解

好板一dp

很明显的一道斜率优化,因为矩阵间不含包含关系,所以当x_{i}>x_{j}时,一定有y_{i}<y_{j}

于是我们先根据x数组从小到大排序,得到序列的y值一定单调下降的。

很明显可以dp了,令dp_{i}为选择第i个矩形且其它所有已选矩形的x值都比其小时,最大的价值和。转移方程式易得:dp_{i}=max\left\{ dp_{j}+(x_{i}-x_{j})\cdot y_{i} -a_{i}\right \}

鉴于n< 10^{6}O\left(n^2 \right )的时间复杂度明显过不了此题,考虑优化。

对于点i,如果点j比点k更优,这有

dp_{j}+ (x_{i}-x_{j})y_{i}-a_{i} > dp_{k}+(x_{i}-x_{k})y_{i}- a{i}

\Rightarrow dp_{j}- x_{j}y_{i}< dp_{k}- x_{k}y_{i}

\Rightarrow dp_{j}-dp_{k}<(x_{j}-x_{k})y_{i}

\Rightarrow \frac{dp_{j}-dp_{k}}{x_{j}-x_{k}}<y_{i}

明显可以通过斜率来优化。时间复杂度O\left(n \right )

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 1000005
typedef long long LL;
typedef pair<int,int> pii;
const LL mo=1e9+7;
const LL INF=0x7f7f7f7f;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
LL n,dp[MAXN],ans;
LL head,tail,q[MAXN];
struct ming{LL x,y,a;}s[MAXN];
bool cmp(ming x,ming y){return x.x<y.x;}
double slope(int x,int y){
	if(s[x].x==s[y].x)return INF;
	return 1.0*(dp[x]-dp[y])/(s[x].x-s[y].x);
}
signed main(){
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
		scanf("%lld %lld %lld",&s[i].x,&s[i].y,&s[i].a);
	sort(s+1,s+n+1,cmp);
	for(int i=1;i<=n;i++){
		while(head+1<tail&&slope(q[head],q[head+1])>=s[i].y)head++;
		dp[i]=s[i].x*s[i].y-s[i].a;
		if(head<tail)dp[i]=max(dp[i],dp[q[head]]+1ll*(s[i].x-s[q[head]].x)*s[i].y-s[i].a);
		while(head+1<tail&&slope(q[tail-2],q[tail-1])<=slope(q[tail-1],i))tail--;q[tail++]=i;
	}
	for(int i=1;i<=n;i++)ans=max(ans,dp[i]);
	printf("%lld\n",ans);
	return 0;
}

谢谢!!!

posted @ 2021-05-22 00:47  StaroForgin  阅读(11)  评论(0)    收藏  举报  来源