题目描述:
思路和AC代码:
方法一:二分+双指针
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define de(x) cout << x << " ";
#define sf(x) scanf("%d", &x);
#define Pu puts("");
const int N = 1e5 + 10;
int n, m;
vector<int> ds[N];
int cnt[N], st[N];
int a[N];
int fun(int mid) {
memset(cnt, 0, sizeof(cnt));
int res = 0;
for (int r = 0, l = 0; r <= n; r++) {
for (auto x : ds[a[r]]) {
if (++cnt[x] == 1) // 第一次覆盖这个因数
res++;
}
while (a[r] - a[l] > mid) {
for (auto x : ds[a[l]]) {
if (--cnt[x] == 0) // 已经不能覆盖这个因数了
res--;
}
l++;
}
if (res == m) // 能够完全覆盖
return 1;
}
return 0;
}
int main() {
int T;
cin >> T;
while (T--) {
cin >> n >> m;
memset(st, 0, sizeof(st));
for (int i = 1; i <= n; i++) {
sf(a[i]);
ds[a[i]].clear();
st[a[i]] = 1;
}
sort(a + 1, a + n + 1);
for (int i = 1; i <= m; i++) { // 对1~m倍数进行因数查找
for (int j = i; j <= a[n]; j += i) {
if (st[j]) {
ds[j].push_back(i);
}
}
}
int l = 0, r = a[n] - a[1] + 1, mid;
while (l < r) {
mid = (l + r) >> 1;
if (fun(mid)) // 这个最小值满足条件,可以更小
r = mid;
else
l = mid + 1;
}
printf("%d\n", (l > a[n] - a[1]) ? -1 : l);
}
}
方法二:双指针
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define de(x) cout << x << " ";
#define sf(x) scanf("%d", &x);
#define Pu puts("");
const int N = 1e5 + 10;
int n, m, ans;
vector<int> ds[N];
int cnt[N], st[N];
int a[N];
int main() {
int T;
cin >> T;
while (T--) {
cin >> n >> m;
memset(st, 0, sizeof(st));
for (int i = 1; i <= n; i++) {
sf(a[i]);
ds[a[i]].clear();
st[a[i]] = 1;
}
sort(a + 1, a + n + 1);
for (int i = 1; i <= m; i++) { // 对1~m倍数进行因数查找
for (int j = i; j <= a[n]; j += i) {
if (st[j]) {
ds[j].push_back(i);
}
}
}
memset(cnt, 0, sizeof(cnt));
int cn = 0;
ans = INT_MAX;
for (int l = 0, r = 0; r <= n; r++) { // 双指针
for (auto x : ds[a[r]]) { // 右指针向后移动
if (++cnt[x] == 1) {
cn++;
}
}
if (cn == m) { // 如果此时已经覆盖了1~m
// 接下来要做的是使得左指针尽可能向右移动,使得差值最小
while (cn == m) {
for (auto x : ds[a[l]]) {
if (--cnt[x] == 0) {
cn--;
}
}
l++;
}
l--; // 退出后不满足,加上前一个正好满足
for (auto x : ds[a[l]]) { // 复原cn
if (++cnt[x] == 1) {
cn++;
}
}
ans = min(ans, a[r] - a[l]); // 更新答案
}
}
printf("%d\n", (ans == INT_MAX) ? -1 : ans);
}
}