【题解】
最开始采用每轮比赛下来再用快排排序的方式,发现都超时了。
分析:
由题意可知每轮比赛下来,胜者们的排序一定是正确的,满足由大到小的顺序;而败者们的排序也一定是正确的,满足由大到小的顺序,由此得到两个有序的序列。
所谓的快排效率高,是针对随机的数列的,而这里每一轮比赛下来,有一半人的相对顺序已经确定了,所以快排就没有了优势。所以针对两个有序序列的排序,使用归并排序更好!
AC代码:
#include <iostream>
#include <algorithm>
using namespace std;
struct st
{
int num, grade, ability;
};
st sh[200005], temp[200005];
st win[200005], lose[200005];
int n, r, q;
bool cmp(const st a, const st b)
{
if (a.grade != b.grade) return a.grade > b.grade;
else return a.num < b.num;
}
void merge()
{
int i = 0, j = 0, l = 0; //i是win下标,j是lose下标,l是temp下标
while (i < n&&j < n) {
if (cmp(win[i], lose[j])) temp[l++] = win[i++];
else temp[l++] = lose[j++];
}
while (i < n) temp[l++] = win[i++];
while (j < n) temp[l++] = lose[j++];
for (int k = 0; k < 2 * n; k++)
sh[k] = temp[k];
}
int main()
{
cin >> n >> r >> q;
for (int i = 0; i < 2 * n; i++)
{
sh[i].num = i + 1;
cin >> sh[i].grade;
}
for (int i = 0; i < 2 * n; i++)
cin >> sh[i].ability;
sort(sh, sh + 2 * n, cmp);
for (int i = 0; i < r; i++)
{
int k = 0; //记录win和lose的下标
for (int j = 0; j < 2 * n; j += 2)
{
if (sh[j].ability > sh[j + 1].ability) {
sh[j].grade += 1;
win[k] = sh[j];
lose[k++] = sh[j + 1];
}
else {
sh[j + 1].grade += 1;
win[k] = sh[j + 1];
lose[k++] = sh[j];
}
}
merge();
}
cout << sh[q - 1].num << endl;
return 0;
}