本文已参与[新人创作礼]活动,一起开启掘金创作之路
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述
这是3月21日代码源div2的每日一题。
锦标赛 - 题目 - Daimayuan Online Judge
题目描述
有n个玩家参加比赛,他们分别有能力值a1,a2,…,an。
需要进行n−1轮比赛,每一轮在剩下的玩家里任选两个玩家i,j。如果|ai−aj|>K,那么其中能力值高的玩家会获胜,能力值低的玩家会被淘汰。如果|ai−aj|≤K,那么两个玩家都有可能获胜,另一个玩家被淘汰。
n−1轮比赛之后,只剩下一个玩家。问有多少个玩家可能是最后获胜的玩家。
输入格式
第一行,两个整数n,K,表示玩家的总人数,和获胜条件中的参数。
接下来一行n个整数a1,a2,…,an,表示玩家的能力值。
输出格式
一个整数,表示最后可能获胜的玩家个数。
样例输入1
5 3
1 5 9 6 3
样例输出1
5
问题分析
这题估摸着很多人对于 “ 如果|ai−aj|≤K,那么两个玩家都有可能获胜,另一个玩家被淘汰 ” 这句话有点疑惑,其实你可以这么理解,如果|ai−aj|≤K,那就由拥有上帝视角的我们来决定谁赢谁输就行,我们这里也就是根据这个来算的最多可能有多少人能胜出。虽然判断获胜的条件有两个,但其实第一个基本用不上,你可以这么想:
能力最大的玩家和能力第二大的玩家,如果他们的差值大于k,那就是最大的获胜,而既然第二大的都赢不了,那不用想其它能力更小的了,这样最终胜出的只能是1个:能力最大的玩家;
但如果第二大的玩家和最大的玩家相差小于等于k,那么这两位都可以胜出,而且只要第三大的和第二大的相差也是小于等于k,那么他们三个人都有可能会获胜:第一大和第二大比完,我们让第二大赢,再让第二大和第三大比,我们让第三大赢。同理第四大也可以以此类推……
由此可推,我们可以知道,最大的获胜人数就是看从最大的能量开始推,看有多少个连着的差都是小于等于k,当有差大于k时,就断开了,因为差值一旦大于k,那么只有大的哪个能赢,小的是无论如何不能活到最后的。小的想赢只能靠我们上帝视角来帮忙,这就必须要差值小于等于k。
(这里写了自定义排序规则让sort降序排,其实没必要这么写,只是个人的习惯)
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define endl '\n';
typedef long long ll;
typedef pair<int, int>PII;
bool cmp(int a, int b)
{
return a > b;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n, k;
cin >> n >> k;
vector<int>v(n);
for (int i = 0; i < n; i++)
cin >> v[i];
sort(v.begin(), v.end(),cmp);
int res = 1;
for (int i = 0; i < n-1; i++)
{
if (v[i] - v[i + 1] <= k)res++;
else break;
}
cout << res << endl;
return 0;
}