洛谷题解-P1309 【瑞士轮】
2018-04-01 13:53
260 查看
原题链接 洛谷博客该题解链接
本题中介绍的瑞士轮赛制,因最早使用于1895年在瑞士举办的国际象棋比赛而得名。它可以看作是淘汰赛与循环赛的折中,既保证了比赛的稳定性,又能使赛程不至于过长。
每轮比赛的对阵安排与该轮比赛开始前的排名有关:第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 的选手的编号。
对于50% 的数据,1 ≤ N ≤ 10,000 ;
对于100%的数据,1 ≤ N ≤ 100,000,1 ≤ R ≤ 50,1 ≤ Q ≤ 2N,0 ≤ s1, s2, …, s2N≤10^8,1 ≤w1, w2 , …, w2N≤ 10^8。
仔细观察发现,不论是得分还是没得分,胜者和败者组成的序列肯定是有序的,那么每次将两个有序的序列组成一个新序列就行了,这便是归并算法可以直接解决的问题了。
先把第一次排序后的数据分为胜者败者两组,胜者分数++后合并,如此反复R次即可完成。
需要注意的是不要偷懒用队列,否则跟快排暴力得分一样,还是老老实实自己用数组模拟吧。
代码及注解如下:
题目内容
题目背景
在双人对决的竞技性比赛,如乒乓球、羽毛球、国际象棋中,最常见的赛制是淘汰赛和循环赛。前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高。后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长。本题中介绍的瑞士轮赛制,因最早使用于1895年在瑞士举办的国际象棋比赛而得名。它可以看作是淘汰赛与循环赛的折中,既保证了比赛的稳定性,又能使赛程不至于过长。
题目描述
2*N 名编号为 1~2N 的选手共进行R 轮比赛。每轮比赛开始前,以及所有比赛结束后,都会按照总分从高到低对选手进行一次排名。选手的总分为第一轮开始前的初始分数加上已参加过的所有比赛的得分和。总分相同的,约定编号较小的选手排名靠前。每轮比赛的对阵安排与该轮比赛开始前的排名有关:第1 名和第2 名、第 3 名和第 4名、……、第2K – 1 名和第 2K名、…… 、第2N – 1 名和第2N名,各进行一场比赛。每场比赛胜者得1 分,负者得 0 分。也就是说除了首轮以外,其它轮比赛的安排均不能事先确定,而是要取决于选手在之前比赛中的表现。
现给定每个选手的初始分数及其实力值,试计算在R 轮比赛过后,排名第 Q 的选手编号是多少。我们假设选手的实力值两两不同,且每场比赛中实力值较高的总能获胜。
输入输出格式
输入格式
输入文件名为swiss.in 。输入的第一行是三个正整数N、R 、Q,每两个数之间用一个空格隔开,表示有 2*N 名选手、R 轮比赛,以及我们关心的名次 Q。
第二行是2*N 个非负整数s1, s2, …, s2N,每两个数之间用一个空格隔开,其中 si 表示编号为i 的选手的初始分数。 第三行是2*N 个正整数w1 , w2 , …, w2N,每两个数之间用一个空格隔开,其中 wi 表示编号为i 的选手的实力值。
输出格式
输出文件名为swiss.out。输出只有一行,包含一个整数,即R 轮比赛结束后,排名第 Q 的选手的编号。
输入输出样例
输入样例
2 4 2 7 6 6 7 10 5 20 15
输出样例
1
说明
数据范围
对于30% 的数据,1 ≤ N ≤ 100;对于50% 的数据,1 ≤ N ≤ 10,000 ;
对于100%的数据,1 ≤ N ≤ 100,000,1 ≤ R ≤ 50,1 ≤ Q ≤ 2N,0 ≤ s1, s2, …, s2N≤10^8,1 ≤w1, w2 , …, w2N≤ 10^8。
来源
Noip2011普及组第3题。题解
显然,每一轮过后次序都会被打乱,所以都需要重新排序。如果每次从头排序(用快排)则只能得60(同学亲测),所以快排不能解决这个问题。仔细观察发现,不论是得分还是没得分,胜者和败者组成的序列肯定是有序的,那么每次将两个有序的序列组成一个新序列就行了,这便是归并算法可以直接解决的问题了。
先把第一次排序后的数据分为胜者败者两组,胜者分数++后合并,如此反复R次即可完成。
需要注意的是不要偷懒用队列,否则跟快排暴力得分一样,还是老老实实自己用数组模拟吧。
代码及注解如下:
#include<bits/stdc++.h> using namespace std; int n,m,a,b,c,d,e,r,q; struct ren{ int s,w,ord; }; ren win[200005],lose[200005]; ren info[200005]; bool com(ren a,ren b) { if (a.s==b.s) return a.ord<b.ord; else return a.s>b.s; } int main() { cin>>n>>r>>q; for (a=1;a<=n*2;a++) cin>>info[a].s; for (a=1;a<=n*2;a++) info[a].ord=a; for (a=1;a<=n*2;a++) cin>>info[a].w; sort(info+1,info+n*2+1,com);//第一次排序可以用快排 for (a=1;a<=r;a++) { for (b=1;b<=n;b++) { if (info[b*2].w>info[b*2-1].w) { info[b*2].s++; win[b]=info[b*2]; lose[b]=info[b*2-1]; } else { info[b*2-1].s++; win[b]=info[b*2-1]; lose[b]=info[b*2]; } }//分成win和lose两组 int e=0; int i=1; int j=1; while (i<=n&&j<=n) { if (win[i].s>lose[j].s) { e++; info[e]=win[i]; i++; } else if (win[i].s<lose[j].s) { e++; info[e]=lose[j]; j++; } else if (win[i].s==lose[j].s)//特别注意要考虑分数相等的情况,把编号小的排在前面 { e++; if (win[i].ord<lose[j].ord) { info[e]=win[i]; i++; } el 4000 se if (win[i].ord>lose[j].ord) { info[e]=lose[j]; j++; } } } if (i>n) while (j<=n) { e++; info[e]=lose[j]; j++; } if (j>n) while (i<=n) { e++; info[e]=win[i]; i++; } }//将原数组覆盖成比赛后的新数组 cout<<info[q].ord; return 0; }
相关文章推荐
- 洛谷P1309 瑞士轮
- NOIP2011 普及组 T3 洛谷P1309 瑞士轮
- |洛谷|排序|P1309 瑞士轮
- 洛谷 P1309 瑞士轮
- 洛谷 P1309 瑞士轮(归并)
- 洛谷 P1309 瑞士轮
- 洛谷P1309 瑞士轮(归并排序)
- 洛谷2763:[网络流24题]试题库问题——题解
- 洛谷3919:可持久化数组——题解
- 洛谷 1373 dp 小a和uim之大逃离 良心题解
- 洛谷3763:[TJOI2017]DNA——题解
- 洛谷3732:[HAOI2017]供给侧改革——题解
- 【题解】 codevs1074 洛谷2024 食物链 详述 《高级数据结构》-林厚从
- 洛谷P1451--求细胞数量_题解
- 【题解】洛谷1200 你的飞碟在这儿…
- 洛谷-3930(我在洛谷上也写了题解)
- 洛谷 p1219题解 八皇后
- 洛谷 p1352 没有上司的舞会 题解
- 洛谷2766:[网络流24题]最长不下降子序列问题——题解
- BZOJ3653 & 洛谷3899:谈笑风生——题解