***题意:***有N个细菌,当且仅当 a i > a j 且 a i ≤ a j + k a_i>a_j且a_i≤a_j+k ai>aj且ai≤aj+k细菌 i i i可以吃 j j j,问最少可能剩下多少细菌?
解法一: 从小到大排个序,每次新加进来一个的时候把,它能吃的的都吃掉,用vector模拟即可。
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6+5;
const int INF = 0x3f3f3f3f;
typedef long long ll;
int n, k, a[MAXN];
int main()
{
scanf("%d%d", &n, &k);
for (int i = 0; i < n; i++) scanf("%d", &a[i]);
sort(a, a+n);
vector<int> S;
for (int i = 0; i < n; i++)
{
while (!S.empty() && a[i] > S.back() && a[i] <= S.back()+k)
S.pop_back();
S.push_back(a[i]);
}
printf("%d\n", S.size());
return 0;
}
/*
7 1
101 53 42 102 101 55 54
*/
解法二: 比赛的时候想到的一种写法,挺麻烦的。。。桶排序,存储一下这些点,然后再求个前缀和。然后每个点只能吃掉它前面的k个点,但是有些点可能已经被吃过了,我们要避免重复吃,所以我们用一个变量pos维护前面已经吃到了哪个位置。对于第 i i i个位置,如果有细菌的话,那么他就可以吃掉 [ i − k − 1 , i − 1 ] [i-k-1,i-1] [i−k−1,i−1]区间内的细菌,考虑上重复吃的情况,那么就是 [ m a x ( i − k − 1 , p o s ) , i − 1 ] [max(i-k-1,pos),i-1] [max(i−k−1,pos),i−1],统计被吃掉了多少就OK了
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6+5;
const int INF = 0x3f3f3f3f;
typedef long long ll;
int n, k, a[MAXN], sum[MAXN];
int main()
{
scanf("%d%d", &n, &k);
for (int i = 0; i < n; i++)
{
int t; scanf("%d", &t);
a[t]++;
}
for (int i = 1; i <= 1e6; i++) sum[i] = sum[i-1]+a[i];
int pos = 0, ans = n;
for (int i = 1; i <= 1e6; i++)
{
if (a[i])
{
ans -= sum[i-1] - sum[max(pos-1, i-k-1)];
pos = i;
}
}
printf("%d\n", ans);
return 0;
}
/*
7 1
101 53 42 102 101 55 54
*/