[CSP-S 2024] 决斗 题解
题目链接
题解
这道题最初的思路是用数值大的打数值小的,而且这一打不能使数值大的那个浪费,先对 \(r\) 数组进行排序(规定从第 \(1\) 项开始)。
sort(r+1,r+1+n);
准确来说,\(r_{i}\) 攻击的是在它之前的没有死亡的元素中的第一个,设 \(f_{i}\) 为在排过序的 \(r\) 数组中截止到第i项,最多会死亡的元素的数量,那么 \(r_{i}\) 应当去攻击 \(r_{f_{i-1}+1}\) 这个元素,只会出现两种情况,第一种,\(r_{i}>r_{f_{i-1}+1}\) ,可知 \(r_{i}\) 可以击败 \(r_{f_{i-1}+1}\),则 \(f_{i}=f_{i-1}+1\),否则(第二种),\(r_{i}=r_{f_{i-1}+1}\),\(r_{i}\)无法击败 \(r_{f_{i-1}+1}\) ,则 \(f_{i}=f_{i-1}\)
易得到状态转移方程式为:
\( f_{i}=\left \{ \begin{matrix} f_{i-1} & ,r_{i}=r_{f_{i-1}+1} \\ f_{i-1}+1& ,r_{i}>r_{f_{i-1}+1} \\ \end{matrix} \right. \)
当 \(i\) 为 \(1\) 时,答案一定是 \(1\),所以 \(i\) 从 \(2\) 开始遍历,最后输出答案\(n-f_{n}\)即可。
凭借这个思路,复杂度控制在了 \(O(n\log_{2}{n}+ n)\)
CODE
#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int r[100005];
int dp[100005];
int main(){
//freopen("duel.in","r",stdin);
//freopen("duel.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&r[i]);
sort(r+1,r+n+1);
for (int i=2;i<=n;i++) dp[i] = r[dp[i-1]+1]==r[i]?dp[i-1]:dp[i-1]+1;
printf("%d",n-dp[n]);
return 0;
}