[CSP-S 2024] 决斗 题解

题目链接

[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;
}
posted @ 2024-11-02 22:37  ZYStream  阅读(85)  评论(0编辑  收藏  举报