Codeforces 1083E The Fair Nut and Rectangles
阿新 • • 發佈:2018-12-26
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); }