codeforces 1083E

luogu鏈接

解法

首先可以觀察到所有矩形排成了類似樓梯的形狀,所以如果對x排序,y也是有序的。
先按x從小到大排序
然後考慮dp:f[i]if[i]表示最後一個矩形選擇的是第i個的最大價值
轉移:f[i]=maxj=1i1(f[i],f[j]+y[i](x[i]x[j])a[i])f[i]=max_{j=1}^{i-1}(f[i],f[j]+y[i]*(x[i]-x[j])-a[i])
考慮優化這個dp:
f[j]+y[i]x[i]y[i]x[j]a[i]f[j]+y[i]*x[i]-y[i]*x[j]-a[i]這個轉移式中:只有y[i]x[j]y[i]*x[j]這一項與i,j都有關,然後又因爲y[i]具有單調性,所以可以考慮斜率優化:
我們觀察和j有關的項,可以認爲x[j]k,f[j]b-x[j]對應k,f[j]對應b,然後考慮斜率優化:如果隊頭和隊頭+1的兩條直線交點的橫座標小於y[i](我們在斜率優化的時候建出的座標系橫座標是y[i]),就把隊頭彈走,隊尾的處理也差不多。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=1e6+5;
inline int read(){
	char c=getchar();int t=0,f=1;
	while((!isdigit(c))&&(c!=EOF)){if(c=='-')f=-1;c=getchar();}
	while((isdigit(c))&&(c!=EOF)){t=(t<<3)+(t<<1)+(c^48);c=getchar();}
	return t*f;
}
int n;
int dp[maxn];
struct node{
	int x,y,a;
}p[maxn];
int h,t;
bool cmp(node a,node b){
	return a.x<b.x;
}
inline double slope(int l,int r){
	return 1.0*(dp[r]-dp[l])/(p[r].x-p[l].x);
}
int q[maxn];
signed main(){
	n=read();
	for(int i=1;i<=n;i++){
		p[i].x=read(),p[i].y=read(),p[i].a=read();
	}
	sort(p+1,p+1+n,cmp);
	h=t=1;
	for(int i=1;i<=n;i++){
		while(h+1<=t&&slope(q[h],q[h+1])>=p[i].y)h++;
		int j=q[h];
		dp[i]=max(dp[i-1],dp[j]+(p[i].x-p[j].x)*p[i].y-p[i].a);
		while(h+1<=t&&slope(q[t-1],q[t])<=slope(q[t],i))t--;
		q[++t]=i;
	}
	printf("%lld\n",dp[n]);
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章