题意不再赘述,思路可以用前缀后缀最大值来写,用一个 l [ i ] l[i] l[i],代表前缀为 i i i最多取多少球, r [ i ] r[i] r[i]代表后缀为 i i i最多为取多少球,枚举 l [ i ] + r [ i + 1 ] l[i]+r[i+1] l[i]+r[i+1]的最大值即可,这样已经避免区间覆盖。
参考代码
/*
* @Author: vain
* @Date: 2020
* @LastEditTime: 2020-10-01 15:29:52
* @LastEditors: sueRimn
* @Description: 学不会 dp 的 fw
* @FilePath: \main\demo.cpp
*/
//#include <bits/stdc++.h>
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <math.h>
#include <bitset>
using namespace std;
typedef long long ll;
#define ll long long
//typedef unsigned long long uint;
const int N = 5000 + 20;
const int maxn = 2e5 + 20;
int a[maxn], vis[maxn];
// typedef pair<int, int> p;
// priority_queue<p, vector<p>, greater<p>> m;
//int sum[maxn];
//ll max(ll a, ll b) { return a > b ? a : b; }
int min(int a, int b) {
return a < b ? a : b; }
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a; }
int lcm(int a, int b) {
return a * b / gcd(a, b); }
void swap(int &x, int &y) {
x ^= y, y ^= x, x ^= y; }
int lowbit(int x) {
return (x) & (-x); }
ll ksm(ll a, ll b)
{
ll res = 1;
for (; b;)
{
if (b & 1)
res *= a;
b >>= 1, a = a * a;
}
return res;
}
int x[maxn], l[maxn], r[maxn];
int main()
{
int t, n, m, k;
scanf("%d", &t);
while (t--)
{
scanf("%d %d", &n, &k);
for (int i = 1; i <= n; i++)
scanf("%d", &x[i]), l[i] = r[i] = 0;
for (int i = 1; i <= n; i++)
scanf("%d", &m);
sort(x + 1, x + n + 1);
int j = n;
r[n + 1] = 0;
for (int i = n; i >= 1; i--)
{
while (j >= 1 && x[i] - x[j] <= k)
j--;
j++;
l[i] = i - j + 1;
}
for (int i = 1; i <= n; i++)
l[i] = max(l[i], l[i - 1]);
j = 1;
for (int i = 1; i <= n; i++)
{
while (j <= n && x[j] - x[i] <= k)
j++;
j--;
r[i] = j - i + 1;
}
for (int i = n; i >= 1; i--)
r[i] = max(r[i], r[i + 1]);
int ans = 0;
for (int i = 1; i <= n; i++)
ans = max(ans, l[i] + r[i + 1]);
printf("%d\n", ans);
}
}