【luogu U138099】大鱼吃小鱼(贪心)

大鱼吃小鱼

题目链接:luogu U138099

题目大意

给你 n 个数,你可以选一些数两两匹配,但条件是大的数至少是小的数的两倍。
然后如果有数没有匹配,则自己视为一对,否则一对匹配算一对。
然后要你最小化对数。

思路

其实这道题可以贪心到爆,就直接按个数分两半,然后直接拿双指针匹配就好了。

我用的是我考场上锅了一点的方法。
就先从小到大排序,然后先找到最小的能吃第一个的数。
然后接着依次吃第二第三第四这样下去,如果不能吃就往后,然后记录空位的个数增加。

然后如果现在被吃的之前吃过人(或者作为了空位),我们考虑还有没有空位。
如果有,那我们可以把空位之前的都往后移一次(移动的是要吃的编号),那你往后移动只会变大,还是可以吃,然后就空出了现在要被吃的可以被吃。
如果没有,那我们就要先吃的整体移一位,留出空位,这个空位再跟新的一位匹配。

要注意的是,没有空位的情况一定要判断是否还有两位或以上,不判只有 75 75 75

代码

#include<cstdio>
#include<algorithm>

using namespace std;

int n, s[500001], kn;
int spl, ans;

int main() {
//	freopen("sj.txt", "r", stdin);
	
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		scanf("%d", &s[i]);
	
	sort(s + 1, s + n + 1);
	
	int r = 1;//先匹配第一个
	while (r <= n && s[r] < s[1] * 2) r++;
	
	if (r > n) {//第一个都匹配不了
		printf("%d", n);
		return 0;
	}
	spl = r;
	
	ans = n - 1; r++;
	for (int i = 2; i <= n; i++) {
		while (r <= n && s[r] < s[i] * 2) {//吃不了,只能跳(这些空位后面要移的时候会用到)
			kn++; r++;
		}
		if (r > n) break;
		if (i < spl) {//之前没有用过这个数,可以直接用
			ans--; r++;
		}
		else {//之前用过,要移出位置用
			if (kn) {//有空位
				kn--;
				r++; ans--;
			}
			else {//没有空位
				if (r + 1 <= n) {//要注意判断能不能移先(我就是这里没了)
					r += 2; ans--;
				}
			}
		}
	}
	
	printf("%d", ans);
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值