一、题目
1、题目描述
2、输入输出
2.1输入
2.2输出
3、原题链接
二、解题报告
1、思路分析
很典的一道题
先将原数组排序
我们定义状态f(i) 代表前 i 个数字是否可以划分,初始化f[0] = true
那么写一个暴力的状态转移:f(i) = f(i) || f(j), i - j <= k && a[i - 1] - a[j] <= d
我们发现随着 i 的增大,j 的 左边界也增大
我们可以双指针边移动i,边移动j
记录[j, i]内 true 的数目 即可
2、复杂度
时间复杂度: O(NlogN)空间复杂度:O(N)
3、代码详解
#include <bits/stdc++.h>
#include <ranges>
#define sc scanf
using i64 = long long;
using i128 = __int128;
using PII = std::pair<int, int>;
constexpr int inf32 = 1e9 + 7;
constexpr i64 inf64 = 1e18 + 7;
constexpr int P = 1e9 + 7;
constexpr double eps = 1e-6;
// #define DEBUG
void solve()
{
int n, k, d;
std::cin >> n >> k >> d;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) std::cin >> a[i];
std::ranges::sort(a);
std::vector<bool> f(n + 1);
f[0] = true;
for (int i = k, j = 0, s = 0; i <= n; ++ i) {
if (f[i - k]) ++ s;
while (a[i - 1] - a[j] > d) {
if (f[j]) -- s;
++ j;
}
f[i] = s > 0;
}
if (f[n])
std::cout << "YES\n";
else
std::cout << "NO\n";
}
int main()
{
#ifdef DEBUG
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
std::ios::sync_with_stdio(false), std::cin.tie(nullptr), std::cout.tie(nullptr);
int _ = 1;
// std::cin >> _;
while (_--)
solve();
return 0;
}