洛谷 P1309 瑞士轮
题目所在网址:https://www.luogu.com.cn/problem/P1309
题目意思并不难理解,就是让你重复做比赛、排序、比赛、排序...这样的工作。但如果真的用快排(sort())去模拟的话,复杂度O(Rnlogn)是过不了的。这里要针对题目特点去变通一下:很明显,假设参赛选手已经排好序,他们打完一架后,胜利的人们拿出来,他们还是有序的,失败的人们拿出来,他们也是有序的,所以在比赛完之后,下一步完全可用归并操作去代替排序操作,将时间复杂度从O(nlogn)降至O(n);这样就能顺利AC掉本题。
注意:只是归并,不是归并排序!!只需要merge(),不需要merge_sort()画蛇添足
附上AC代码:
- #include<iostream>
- #include<algorithm>
- #include<fstream>
- #include<vector>
- using namespace std;
- const int MAXN = 2e5 + 5;
- class athletes{
- public:
- int id, score, power;
- athletes(){
- }
- athletes(int id, int score){
- this->id = id;
- this->score = score;
- }
- athletes(const athletes& a){
- this->id = a.id;
- this->score = a.score;
- this->power = a.power;
- }
- };
- athletes game[MAXN], winner[MAXN], loser[MAXN];
- bool cmp(const athletes& a, const athletes& b){
- if(a.score != b.score)return a.score > b.score;
- return a.id < b.id;
- }
- void merge(athletes game[], athletes winner[], athletes loser[], int n){
- int i = 1, j = 1, l = 1;
- while(i <= n || j <= n){
- if(i > n){
- game[l++] = loser[j++];
- continue;
- }
- if(j > n){
- game[l++] = winner[i++];
- continue;
- }
- if(cmp(winner[i], loser[j])){
- game[l++] = winner[i++];
- }
- else game[l++] = loser[j++];
- }
- }
- int main(){
- // ifstream cin("data.txt");
- // ios::sync_with_stdio(false);
- int n, r, q, temp;
- cin >> n >> r >> q;
- for(int i = 1; i <= n * 2; i++){
- game[i].id = i;
- cin >> game[i].score;
- }
- for(int i = 1; i <= n * 2; i++){
- cin >> game[i].power;
- }
- sort(game + 1, game + 2 * n + 1, cmp);
- while(r--){
- for(int i = 1; i < 2 * n; i += 2){
- if(game[i].power > game[i + 1].power){
- game[i].score++;
- winner[(i + 1) / 2] = game[i];
- loser[(i + 1) / 2] = game[i + 1];
- }
- else{
- game[i + 1].score++;
- winner[(i + 1) / 2] = game[i + 1];
- loser[(i + 1) / 2] = game[i];
- }
- }
- merge(game, winner, loser, n);
- }
- cout << game[q].id;
- return 0;
- }
- //2020.3.10
- //每次比赛完后,分胜者组和败者组,两组内已经是顺序的,无需排序,O(n)归并一下就好