试题描述
|
【背景】在双人对决的竞技性比赛,如乒乓球、羽毛球、国际象棋中,最常见的赛制是淘汰赛和循环赛。前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高。后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长。本题中介绍的瑞士轮赛制,因最早使用于1895年在瑞士举办的国际象棋比赛而得名。它可以看作是淘汰赛与循环赛的折衷,既保证了比赛的稳定性,又能使赛程不至于过长。 |
输入
|
输入的第一行是三个正整数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
|
其他说明
|
【数据范围】1≤N≤100,000,1≤R≤50,1≤Q≤2N,0≤s1,s2,…,s2N≤100000000,1≤w1,w2,…,w2N≤100000000。
|
C程序:
#include <cstdio> #include <cstdlib> #include <algorithm> using namespace std; int N,R,Q; struct node { int s,w,p; }t[210000],first[210000],second[210000]; bool cmp(node x,node y) { if(x.s<y.s) return false; if(x.s>y.s) return true; if(x.p<y.p) return true; return false; } void input() { //freopen("swiss.in","r",stdin); //freopen("swiss.out","w",stdout); scanf("%d%d%d",&N,&R,&Q); for(int i=1;i<=2*N;i++) scanf("%d",&t[i].s); for(int i=1;i<=2*N;i++) scanf("%d",&t[i].w); for(int i=1;i<=2*N;i++) t[i].p=i; } void work() { sort(t+1,t+2*N+1,cmp); while(R--) { for(int i=1;i<=2*N;i+=2) if(t[i].w>t[i+1].w) { t[i].s++; first[(i+1)/2]=t[i]; second[(i+1)/2]=t[i+1]; } else { t[i+1].s++; first[(i+1)/2]=t[i+1]; second[(i+1)/2]=t[i]; } int x=1,y=1,cnt=0; while(x<=N && y<=N) if(first[x].s>second[y].s) t[++cnt]=first[x++]; else if(first[x].s<second[y].s) t[++cnt]=second[y++]; else { if(first[x].p<second[y].p) t[++cnt]=first[x++]; else t[++cnt]=second[y++]; } while(x<=N) t[++cnt]=first[x++]; while(y<=N) t[++cnt]=second[y++]; //sort(t+1,t+2*N+1,cmp); } printf("%d\n",t[Q].p); } int main() { input(); work(); return 0; }