cychester

Codeforces 1083E The Fair Nut and Rectangles

Description

\(N\)个左下定点为原点的矩阵, 每个矩阵\((x_i,~y_i)\)都有一个数\(a_i\)表示其花费。

没有一个矩阵包含另一个矩阵。

现要你选出若干个矩阵, 使得矩阵组成的图形的大小减去总花费得到的数最大

Solution

先按照\(x_i\) 递增排序, 由于矩阵互不包含, 所以\(y_i\)递减。 就可以列出\(DP\)方程:

\[f_i~=~(x_i~-~x_j)~ \times~ y_i~-~a_i~+~f_j~~~~~~~~(j<i) \]

可以拆成斜率优化方程:

\[f_j~=~y_i~\times~x_j~+~a_i~-~x_i~\times~y_i~+~f_i \]

上斜率优化板子就AC了, 复杂度\(O(N)\)

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define up(a, b) (a = a > b ? a : b)
#define down(a, b) (a = a > b ? b : a)
#define cmax(a, b) (a > b ? a : b)
#define cmin(a, b) (a > b ? b : a)
#define Abs(a) ((a) > 0 ? (a) : -(a))
#define rd read()
#define db double
#define LL long long
using namespace std;
typedef pair<int, int> P;

inline char nc(){
    static char buf[1<<14],*p1=buf,*p2=buf;
    return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<14,stdin),p1==p2)?EOF:*p1++;
}
inline LL read(){
    char c=nc();LL x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=nc();}
    while(c>='0'&&c<='9'){x=x*10+c-'0',c=nc();}
    return x*f;
}

const int N = 1e6 + 1e5;

int n, q[N];
LL ans = 0, f[N];

struct node {
	int x, y;
	LL w;
	bool operator < (const node &b) const {
		return x < b.x;
	}
}a[N];

double calk(int A, int B) {
	double ax = a[A].x, bx = a[B].x;
	double ay = f[A], by = f[B];
	return (ay - by) / (ax - bx);
}

int main()
{
	n = rd;
	for (int i = 1; i <= n; ++i) {
		a[i].x = rd;
		a[i].y = rd;
		a[i].w = rd;
	}	
	sort(a + 1, a + 1 + n);
	int l = 1, r = 1;
	for (int i = 1; i <= n; ++i) {
		while (l < r && calk(q[l], q[l + 1]) >= a[i].y)
			l++;
		int tmp = q[l];
		f[i] = (1LL * a[i].x - a[tmp].x) * a[i].y - a[i].w + f[tmp];
		up(ans, f[i]);
		while (l < r && calk(q[r], q[r - 1]) <= calk(q[r], i))
			r--;
		q[++r] = i;
	}
	printf("%lld\n", ans);
}

posted on 2018-12-26 20:48  cychester  阅读(394)  评论(0编辑  收藏  举报

导航