洛谷 P1309 瑞士轮

题目所在网址:https://www.luogu.com.cn/problem/P1309

题目意思并不难理解,就是让你重复做比赛、排序、比赛、排序...这样的工作。但如果真的用快排(sort())去模拟的话,复杂度O(Rnlogn)是过不了的。这里要针对题目特点去变通一下:很明显,假设参赛选手已经排好序,他们打完一架后,胜利的人们拿出来,他们还是有序的,失败的人们拿出来,他们也是有序的,所以在比赛完之后,下一步完全可用归并操作去代替排序操作,将时间复杂度从O(nlogn)降至O(n);这样就能顺利AC掉本题。

注意:只是归并,不是归并排序!!只需要merge(),不需要merge_sort()画蛇添足

附上AC代码:

  1. #include<iostream>  
  2. #include<algorithm>  
  3. #include<fstream>  
  4. #include<vector>  
  5. using namespace std;  
  6.   
  7. const int MAXN = 2e5 + 5;  
  8.   
  9. class athletes{  
  10. public:  
  11.     int id, score, power;  
  12.     athletes(){  
  13.     }  
  14.     athletes(int id, int score){  
  15.         this->id = id;  
  16.         this->score = score;  
  17.     }  
  18.     athletes(const athletes& a){  
  19.         this->id = a.id;  
  20.         this->score = a.score;  
  21.         this->power = a.power;  
  22.     }  
  23. };  
  24.   
  25. athletes game[MAXN], winner[MAXN], loser[MAXN];  
  26.   
  27. bool cmp(const athletes& a, const athletes& b){  
  28.     if(a.score != b.score)return a.score > b.score;  
  29.     return a.id < b.id;  
  30. }   
  31.   
  32. void merge(athletes game[], athletes winner[], athletes loser[], int n){  
  33.     int i = 1, j = 1, l = 1;  
  34.     while(i <= n || j <= n){  
  35.         if(i > n){  
  36.             game[l++] = loser[j++];  
  37.             continue;  
  38.         }  
  39.         if(j > n){  
  40.             game[l++] = winner[i++];  
  41.             continue;  
  42.         }  
  43.         if(cmp(winner[i], loser[j])){  
  44.             game[l++] = winner[i++];  
  45.         }  
  46.         else game[l++] = loser[j++];  
  47.     }  
  48. }  
  49.   
  50. int main(){  
  51. //  ifstream cin("data.txt");  
  52. //  ios::sync_with_stdio(false);  
  53.     int n, r, q, temp;  
  54.     cin >> n >> r >> q;  
  55.     for(int i = 1; i <= n * 2; i++){  
  56.         game[i].id = i;  
  57.         cin >> game[i].score;  
  58.     }  
  59.     for(int i = 1; i <= n * 2; i++){  
  60.         cin >> game[i].power;  
  61.     }  
  62.     sort(game + 1, game + 2 * n + 1, cmp);  
  63.     while(r--){  
  64.         for(int i = 1; i < 2 * n; i += 2){  
  65.             if(game[i].power > game[i + 1].power){  
  66.                 game[i].score++;  
  67.                 winner[(i + 1) / 2] = game[i];  
  68.                 loser[(i + 1) / 2] = game[i + 1];  
  69.             }  
  70.             else{  
  71.                 game[i + 1].score++;  
  72.                 winner[(i + 1) / 2] = game[i + 1];  
  73.                 loser[(i + 1) / 2] = game[i];  
  74.             }  
  75.         }  
  76.         merge(game, winner, loser, n);  
  77.     }  
  78.     cout << game[q].id;  
  79.     return 0;  
  80. }   
  81. //2020.3.10  
  82. //每次比赛完后,分胜者组和败者组,两组内已经是顺序的,无需排序,O(n)归并一下就好    
posted @ 2020-03-11 19:27  sheeeeeeep  阅读(106)  评论(0编辑  收藏  举报