P3143. Diamond Collector S

考点

  • 双指针

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e4 + 50;
int n, k, a[maxn], lmx[maxn], rmx[maxn];

int main() {
cin >> n >> k;
for (int i = 1; i <= n; ++i) cin >> a[i];
sort(a + 1, a + 1 + n);
for (int l = n, r = n; r >= 1; --r) {
while (l >= 1 && a[r] - a[l] <= k) {
rmx[l] = max(rmx[l + 1], r - l + 1);
--l;
}
}
for (int l = 1, r = 1; l <= n; ++l) {
while (r <= n && a[r] - a[l] <= k) {
lmx[r] = max(lmx[r - 1], r - l + 1);
++r;
}
}
int ans = 0;
for (int i = 1; i <= n; ++i) {
ans = max(ans, lmx[i] + rmx[i + 1]);
}
cout << ans;
return 0;
}

思路

一个区间内的任意两元素差值在k以内,保证该区间最大值和最小值差值在k以内即可;故而先将数组排序。

由于每个元素会被重复选择,比如:

  1. 该元素作为某区间的最小值
  2. 该元素作为某区间的最大值

故而必须分开讨论:

  1. 用双指针,lr默认值均为n

    即以从大到小的顺序,计算以l作为左端点(区间最小)时,向右最大扩展的区间长度r - l + 1;

    同时令rmx[i]记录i、i + 1、i + 2...n中某个最大的向右扩展长度

  2. 用双指针,lr默认值均为1

    即以从小到大的顺序,计算以r作为右端点(区间最大)时,向左最大扩展的区间长度r - l + 1;

    同时令lmx[i]记录1、2、3...i中某个最大的向左扩展长度

所以,最后只需要再扫一遍打擂台,计算lmx[i] + rmx[i + 1]的最大值即可。