CF 1203 Boxers
题意:
n个拳击手,每个体重都可以减一 加一 或不变,问该怎么操作才能使不同体重拳击手数量最多。
思路:
贪心思想,先记录每个体重有多少人,一个体重最多能扩展成3种体重,所以从小到大开始要先将体重-1看是否已经存在,若存在,则不变,若原体重存在则判断+1是否存在,若都不存在就将该体重进行标记,若是从大到小循环,则是优先级反过来。解释为什么要向一端移动,因为要尽可能给能扩展成两个或三个体重的体重让位置,所以要向递增或递减方向移动。
注意要特判体重为1的选手。
引用如下代码
#include<string.h>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
using namespace std;
#define ll long long
ll a[200000];
ll tp[150005];
ll tp2[150005];
int main() {
ll n;
scanf("%lld",&n);
//这里是两个桶排,tp 记录的是不同体重选手的数量
//tp2 记录的是某个体重是否被加入队伍中。
memset(tp, 0, sizeof(tp));
memset(tp2, 0, sizeof(tp2));
for(int i = 0; i < n; i++) {
scanf("%lld",&a[i]);
tp[a[i]]++;
}
for(int i = 1; i < 150001; i++) {
if(i == 1) {
//这里特判体重为1的选手
if(tp[i] != 0) {
tp2[i]++;
tp[i]--;
}
if(tp[i] != 0) {
tp2[i+1]++;
tp[i]--;
}
}
else {
if(tp[i] != 0) {
//优先降低体重
if(tp2[i-1] == 0) {
tp2[i-1]++;
tp[i]--;
}
//然后保持体重
if(tp[i] != 0 && tp2[i] == 0) {
tp[i]--;
tp2[i]++;
}
//最后才是提升体重。
if(tp[i] != 0 && tp2[i+1] == 0) {
tp[i]--;
tp2[i+1]++;
}
}
}
}
ll ans = 0;
for(int i = 0; i < 150005; i++) {
if(tp2[i] != 0)
ans++;
}
cout << ans << endl;
return 0;
}