洛谷 P3143 [USACO16OPEN]钻石收藏家Diamond Collector

传送门

思路

把所有钻石排序,显然最优解会是排序后的一个区间。(易用反证法证明)

那么从小到大枚举这个区间的右端点\(r\),能够满足条件的最靠左的右端点\(l\)单调不降

建立变量\(now\)\(r\) , \(now\)表示某位置左边最多可以放多少颗钻石(即放在第一个架子上),\(r\)表示从某位置向右最多可以延伸到的位置(即在第二个架子上)

然后从前往后跑一遍就行了

代码

//知识点:贪心,排序 
/*
By:Loceaner
*/
#include 
#include 
#include 
#include 
#define int long long
using namespace std;

inline int read() {
    char c = getchar();
    int x = 0, f = 1;
    for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    return x * f;
}

const int N = 5e4 + 11;

int n, k, a[N], l[N], r = 1, ans = 0, now;

signed main() {
    n = read(), k = read();
    for(int i = 1; i <= n; i++) a[i] = read();
    stable_sort(a + 1, a + 1 + n);
    for(int i = 1; i <= n; i++) {
        while(a[r] <= a[i] + k && r <= n) r++;
        l[r] = max(l[r], r - i);
        now = max(now, l[i]);
        ans = max(ans, now + r - i);
    }
    cout << ans << '\n';
    return 0;
}

你可能感兴趣的:(洛谷 P3143 [USACO16OPEN]钻石收藏家Diamond Collector)