蓝桥杯 PREV-50 对局匹配(贪心)

题目链接:

PREV-50 对局匹配

思路:

1.我们将分数模 k k k相同的放在一组,我们知道只有同一组的人才有可能相互匹配到;
2.我们遍历每一组,按公差为 k k k的分数顺序将该分数的人数组成一个序列,例如所有分数为 [ 2 , 2 , 4 , 5 , 3 , 4 , 5 , 1 , 8 ] [2,2,4,5,3,4,5,1,8] [2,2,4,5,3,4,5,1,8] k k k 2 2 2,则模 k k k 0 0 0的一组分数为 [ 2 , 2 , 4 , 4 , 8 ] [2,2,4,4,8] [2,2,4,4,8],那么我们可以得到一个序列 [ 0 , 2 , 2 , 0 , 1 ] [0,2,2,0,1] [0,2,2,0,1](0的个数为0, 2的个数为2,4的个数为2,6的个数为0,8的个数为1,…当然后面还有10,12,14等等的个数,只不过都为0);
3.对于每一组我们都可以得到相应的序列,我们的目标就是求:
进行操作p:使序列相邻的数可以删除同样的值;我们的目的就是进行多轮操作p后使该序列相邻的数不都大于 0 0 0,且序列和最大;
我们需要求得每一个序列进行完操作后的最大和,将它们累加就是最终答案;
4.对于上述操作,使用贪心可以很简洁明了地求得;
5.k为0需要单独考虑;

代码:

#include<bits/stdc++.h>

using namespace std;

const int maxn = 1e5 + 5;
int n, k, cnt[maxn];

int main() {
    
    
#ifdef MyTest
	freopen("Sakura.txt", "r", stdin);
#endif
	scanf("%d %d", &n, &k);
	int a, ans = 0;
	for(int i = 0; i < n; i++) {
    
    
		scanf("%d", &a);
		++cnt[a];
		if(cnt[a] == 1 && k == 0) ++ans;	
	}
	if(k == 0) cout << ans, exit(0);
	for(int i = 0; i < maxn; i++) {
    
    
		if(cnt[i] == 0) continue;
		if(i + k >= maxn) break;
		int p = min(cnt[i], cnt[i + k]);
		ans += p, cnt[i] -= p, cnt[i + k] -= p;
	}
	cout << n - ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_45228537/article/details/104536938