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);
}

猜你喜欢

转载自www.cnblogs.com/cychester/p/10181705.html
今日推荐