试题描述
|
【背景】在双人对决的竞技性比赛,如乒乓球、羽毛球、国际象棋中,最常见的赛制是淘汰赛和循环赛。前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高。后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长。本题中介绍的瑞士轮赛制,因最早使用于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。
|
一个SB题,我竟然WA了N发?!?!?!
每次得到有序的两个序列,合并即可。
宏定义不知道慢到哪里去了。
#include<cstdio> #include<cctype> #include<queue> #include<cstring> #include<algorithm> #define lc ch[x][0] #define rc ch[x][1] #define rep(s,t) for(int i=s;i<=t;i++) #define ren for(int i=first[x];i!=-1;i=next[i]) using namespace std; inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f; } const int maxn=200010; struct Player { int id,s,w; bool operator < (const Player& ths) const { if(s!=ths.s) return s<ths.s; return id>ths.id; } }A[maxn],B[maxn]; int n,R,q; int main() { n=read()<<1;R=read();q=read(); rep(1,n) A[A[i].id=i].s=read(); rep(1,n) A[i].w=read(); sort(A+1,A+n+1);reverse(A+1,A+n+1); rep(1,R) { rep(1,n>>1) { int a=(i<<1)-1,b=i<<1; if(A[a].w>A[b].w) A[a].s++;else A[b].s++; if(A[a]<A[b]) swap(A[a],A[b]); } int l=1,r=2,t=0; rep(1,n) if((l<=n&&A[r]<A[l])||r>n) B[++t]=A[l],l+=2; else B[++t]=A[r],r+=2; rep(1,n) A[i]=B[i]; } printf("%d ",A[q].id); return 0; }