P3143 [USACO16OPEN]钻石收藏家Diamond Collector[two-pointers]

Posted garen-wang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3143 [USACO16OPEN]钻石收藏家Diamond Collector[two-pointers]相关的知识,希望对你有一定的参考价值。

P3143 [USACO16OPEN]钻石收藏家Diamond Collector

题意要注意一点:有两个陈列架!

如果只有一个陈列架,是很容易的。two-pointers直接从左到右跑一下即可。

如果有两个陈列架,就需要进行答案合并了。做法是这样的:

设两个数组:

  1. (pre)数组,(pre[i])表示以([1,i])为右端点时区间长度的最大值。
  2. (suf)数组,(suf[i])表示以([i,n])为左端点时区间长度的最大值。

两个数组分别是前缀最大值和后缀最大值。同样利用一个陈列架的two-pointers的做法。

最后的答案就是(max_{i=1}^{n+1} pre[i-1] + suf[i])。这里的(i)相当于拼接点。

代码:

#include<bits/stdc++.h>
using std::cin;
using std::cout;
using std::endl;
#define ll long long
const int maxn = 50005;
int a[maxn];
int pre[maxn], suf[maxn];
int n, k;

void work1() {
    for(int r = 1, l = 0; r <= n; r++) {
        while(a[r] - a[l + 1] > k) l++;
        pre[r] = std::max(pre[r - 1], r - l);
    }
}
void work2() {
    for(int l = n, r = n + 1; l >= 1; l--) {
        while(a[r - 1] - a[l] > k) r--;
        suf[l] = std::max(suf[l + 1], r - l);
    }
}
int main() {
    cin >> n >> k;
    for(int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    std::sort(a + 1, a + n + 1);
    work1();
    work2();
    int ans = 0;
    for(int i = 1; i <= n + 1; i++) {
        ans = std::max(ans, pre[i - 1] + suf[i]);
    }
    cout << ans << endl;
    return 0;
}

以上是关于P3143 [USACO16OPEN]钻石收藏家Diamond Collector[two-pointers]的主要内容,如果未能解决你的问题,请参考以下文章

P3143 [USACO16OPEN]钻石收藏家Diamond Collector(伸缩法)

P3143 [USACO16OPEN]钻石收藏家Diamond Collector[two-pointers]

Luogu P3143 [USACO16OPEN]钻石收藏家Diamond Collector 题解

洛谷 P3147 [USACO16OPEN]262144

洛谷 P3146 [USACO16OPEN]248

洛谷P3146 [USACO16OPEN]248