瑞士輪
時間限制: 1 Sec 內存限制: 128 MB題目描述
在雙人對決的競技性比賽,如乒乓球、羽毛球、國際象棋中,最常見的賽制是淘汰賽和循環賽。前者的特點是比賽場數少,每場都緊張刺激,但偶然性較高。后者的特點是較為公平,偶然性較低,但比賽過程往往十分冗長。
本題中介紹的瑞士輪賽制,因最早使用於1895年在瑞士舉辦的國際象棋比賽而得名。它可以看作是淘汰賽與循環賽的折衷,既保證了比賽的穩定性,又能使賽程不至於過長。
2*N名編號為1~2N的選手共進行R輪比賽。每輪比賽開始前,以及所有比賽結束后,都會對選手進行一次排名。排名的依據是選手的總分。選手的總分為第一輪開始前的初始分數加上已參加過的所有比賽的得分和。總分相同的,約定編號較小的選手排名靠前。
每輪比賽的對陣安排與該輪比賽開始前的排名有關:第1名和第2名、第3名和第4名、……、第2K – 1名和第2K名、…… 、第2N – 1名和第2N名,各進行一場比賽。每場比賽勝者得1分,負者得0分。也就是說除了首輪以外,其它輪比賽的安排均不能事先確定,而是要取決於選手在之前比賽中的表現。
現給定每個選手的初始分數及其實力值,試計算在R輪比賽過后,排名第Q的選手編號是多少。我們假設選手的實力值兩兩不同,且每場比賽中實力值較高的總能獲勝。
輸入
輸入的第一行是三個正整數N、R、Q,每兩個數之間用一個空格隔開,表示有2*N名選手、R輪比賽,以及我們關心的名次Q。
第二行是2*N個非負整數s1, s2, …, s2N,每兩個數之間用一個空格隔開,其中si表示編號為i的選手的初始分數。
第三行是2*N個正整數w1, w2, …, w2N,每兩個數之間用一個空格隔開,其中wi表示編號為i的選手的實力值。
輸出
輸出只有一行,包含一個整數,即R輪比賽結束后,排名第Q的選手的編號。
樣例輸入
2 4 2 7 6 6 7 10 5 20 15
樣例輸出
1
提示

#include <iostream> #include <bits/stdc++.h> using namespace std; const int maxn=1e6+10; int s[maxn],n,r,q; struct node { int val,abl,pos; } e[maxn],temp[maxn],win[maxn],lose[maxn]; bool cmp(node a,node b) { if(a.val!=b.val) return a.val>b.val; return a.pos<b.pos; } void gb(int x,int y) { int i=0,j=0,k=1; while(i<x&&j<y) { if(win[i].val<lose[j].val) { e[k++]=lose[j++]; } else if(win[i].val>lose[j].val) { e[k++]=win[i++]; } else { if(win[i].pos<lose[j].pos) e[k++]=win[i++]; else e[k++]=lose[j++]; } } while(j<y) { e[k++]=lose[j++]; } while(i<x) { e[k++]=win[i++]; } // for(int i=0; i<k; i++) // { // e[star+i]=temp[i]; // } } //void GBsort(node *e,int star,int endd) //{ // if(e==NULL||star>=endd) // return ; // int mid=(star+endd)/2; // GBsort(e,star,mid); // GBsort(e,mid+1,endd); // gb(star,mid,endd); //} int main() { std::ios::sync_with_stdio(false); cin>>n>>r>>q; n*=2; for(int i=1; i<=n; i++) { cin>>e[i].val; e[i].pos=i; } for(int i=1; i<=n; i++) { cin>>e[i].abl; } sort(e+1,e+1+n,cmp); while(r--) { int x=0,y=0; for(int i=1; i<=n; i+=2) { if(e[i].abl>e[i+1].abl) { e[i].val++; win[x++]=e[i]; lose[y++]=e[i+1]; } else { e[i+1].val++; win[x++]=e[i+1]; lose[y++]=e[i]; } } gb(x,y); } cout<<e[q].pos<<endl; return 0; }