1 条题解
-
0
思路与算法
首次按分数降序与编号升序排序;每轮原序列的胜者和败者分别有序,给胜者加1以后线性归并,避免每轮完整排序。
正确性说明
胜者按原排名取子序列且都加1,故内部排序关系不变;败者不加分也维持原序。两条有序列归并后就是本轮的正确排名,由初排归纳至最后一轮。
复杂度
O(N log N+RN)时间、O(N)空间;这里N为单侧人数,实际人数2N,初排与两组临时数组均计入。
易错点
相同分数比较编号,不能按实力打破排名平局;实力只用于相邻两人对局。
参考代码(C++11)
#include <bits/stdc++.h> using namespace std; struct P { int id, s, w; }; bool cmp(P a, P b) { return a.s != b.s ? a.s > b.s : a.id < b.id; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, r, q; cin >> n >> r >> q; n *= 2; vector<P> a(n), tmp(n), win, lose; for (int i = 0; i < n; i++) { a[i].id = i + 1; cin >> a[i].s; } for (auto &p : a) cin >> p.w; sort(a.begin(), a.end(), cmp); while (r--) { win.clear(); lose.clear(); for (int i = 0; i < n; i += 2) { P x = a[i], y = a[i + 1]; if (x.w < y.w) swap(x, y); x.s++; win.push_back(x); lose.push_back(y); } merge(win.begin(), win.end(), lose.begin(), lose.end(), tmp.begin(), cmp); a.swap(tmp); } cout << a[q - 1].id << "\n"; }
- 1