P11231 [CSP-S 2024] 决斗题解

题目描述

今天是小 Q 的生日,他得到了 nn 张卡牌作为礼物。这些卡牌属于火爆的“决斗怪兽”,其中,第 ii 张卡代表一只攻击力为 riri​,防御力也为 riri​ 的怪兽。

一场游戏分为若干回合。每回合,小 Q 会选择某只怪兽 i 以及另一只怪兽 j(i≠j),并让怪兽 ii 向怪兽 jj 发起攻击。此时,若怪兽 ii 的攻击力小于等于怪兽 j 的防御力,则无事发生;否则,怪兽 jj 的防御被打破,怪兽 jj 退出游戏不再参与到剩下的游戏中。一只怪兽在整场游戏中至多只能发起一次攻击。当未退出游戏的怪兽都已发起过攻击时,游戏结束。

小 Q 希望决定一组攻击顺序,使得在游戏结束时,未退出游戏的怪兽数量尽可能少。

输入格式

输入的第一行包含一个正整数 n,表示卡牌的个数。

输入的第二行包含 n 个正整数,其中第 i 个正整数表示第 i 个怪兽的攻击力及防御力 ri​。

输出格式

输出一行包含一个整数表示游戏结束时未退出游戏的怪兽数量的最小值。

输入输出样例

输入 #1

5
1 2 3 1 2

输出 #1

2

输入 #2

10
136 136 136 2417 136 136 2417 136 136 136

输出 #2

8

简述题意

每个怪兽有一个实力 ri​,每个怪兽只可以欺负实力严格小于自己的怪兽,被成功欺负的怪兽出局。当未退出游戏的怪兽都已发起过攻击时,游戏结束。规定一种方案使得未退出游戏的怪兽数量尽可能少。

算法分析

显然,对于 a<ri,b<ri,a,b 在 rii 面前是等价的(都能被欺负)。

定义 sumksumk​ 表示 ri=k 的怪兽个数,cnt 为对于实力为 [1,i−1] 的怪兽的最优解。

所以按实力从小到大欺负,有两种情况:

  • 如当前 sumk≤cnt,欺负 sumk​ 只即可。即 cnt←cnt。
  • 否则,欺负当前所有怪兽,即 cnt←sumk​。

上面的过程可看做 cnt=max⁡sumkcnt=maxsumk​。

然后这题就做完了。


诶等等,如果这个数据:

3
1 2 2

有一只怪兽好像没有欺负别人啊?

其实让剩下相同的再互相欺负一遍即可。


时间复杂度 O(n+A)O(n+A),AA 为 riri​ 的值域。

代码实现

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[100005];
signed main()
{
	int n,x,ans=0;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int x;
		cin>>x;
		a[x]++;
	}
	for(int i=1;i<=100000;i++) ans=max(ans,a[i]);
	cout<<ans;
	return 0;
}

在百忙之中写一篇题解也比较辛苦,麻烦拿拿你们皇帝般的纤纤玉手帮我点点赞。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值