NOIP2011普及组 瑞士轮
OJ地址:
https://www.luogu.org/problemnew/show/P1309
http://bailian.openjudge.cn/practice/4031/
- 总时间限制: 2000ms 单个测试点时间限制: 1000ms 内存限制: 65535kB
- 描述
-
【背景】
在双人对决的竞技性比赛,如乒乓球、羽毛球、国际象棋中,最常见的赛制是淘汰赛和循环赛。前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高。后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长。
本题中介绍的瑞士轮赛制,因最早使用于 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
提示
对于 30%的数据,1 ≤ N ≤ 100;
对于 50%的数据,1 ≤ N ≤ 10,000;
对于 100%的数据, 1 ≤ N ≤ 100,000, 1 ≤ R ≤ 50, 1 ≤ Q ≤ 2N, 0 ≤ s1, s2, …, s2N ≤ 108, 1 ≤ w1, w2, …, w2N ≤ 108。
算法分析:
参考https://blog.csdn.net/dengping_ss/article/details/49833557
对于这道题,最容易想到的算法恐怕就是直接模拟比赛过程,每轮比赛前都用快排排一次,然后再根据选手的实力值决定胜负。但是这样算下来,时间复杂度达到了O(R*(N*logN+N)),但实际动作的次数还要加一个常数倍,因为一共有2*N个人。
把数据范围看一下,就知道这种算法肯定是要超时的,因此只要还有时间,应该尝试更为高效的算法。
很容易可以知道,每轮比赛结束后,胜利者和失败者两个群体中内部的顺序是不会被打乱的。也就是说,第一轮比赛后每一对人中的胜利者拿来排序之后跟原来他们比赛前的顺序是一样的,当然失败者的一群人也一样。因此,很容易就想到之前那个算法为什么不够高效了,因为快排的效率高是针对随机的数列的,而这里每一轮比赛下来,有许多人(一半人)的相对顺序已经确定了。因此就想到了归并排序,这样,每一轮比赛后用O(N)的复杂度归并一次就好,而不用快排,那样会损失掉已有的信息。这样,估算下来,时间就够了。
值得注意的是:在第一轮比赛前,并不知道待比赛选手的排名,而这时又不可能得到任何已有的信息,因为本来直接给出的初始值s是无序的,所以这时应使用快排,而且要注意初始值相同的情况,但这里已经是细节,不是重点了。
另外,每一轮比赛过程中,两个人进行一场比赛后,这两人都应该分到两个临时数组(这两个数组分别代表胜利者群体和失败者群体)以便后续的归并操作。这个时候要特别注意:这一场比赛的两个人若是打平手了,那么两人都应该分到失败者群体,因为他们两人的积分都没有增加。
AC代码如下:
#include<stdio.h>
#include<stdlib.h>
struct person
{
int ID,s,w;//选手编号、分值、实力值
};
int cmp(const void *a,const void *b)
{
struct person *x,*y;
x=(struct person*)a;
y=(struct person*)b;
if(x->s > y->s) return -;
else if(x->s < y->s) return ;
else
{
if(x->ID > y->ID) return ;
else return ;
}
}
int main()
{
int N,R,Q;
struct person *a=NULL,*b=NULL,*c=NULL;
int i,j,NN,kb,kc,ib,ic; scanf("%d%d%d",&N,&R,&Q);
NN=*N;
a=(struct person *)malloc(sizeof(struct person)*NN);
b=(struct person *)malloc(sizeof(struct person)*NN);
c=(struct person *)malloc(sizeof(struct person)*NN); for(i=;i<NN;i++)
{
a[i].ID=i+;
scanf("%d",&a[i].s);
}
for(i=;i<NN;i++)
scanf("%d",&a[i].w);
qsort(a,NN,sizeof(a[]),cmp); for(i=;i<R;i++)
{
kb=kc=;
for(j=;j<NN;j=j+)//模拟一轮比赛
{
if(a[j].w>a[j+].w) { a[j].s++; b[kb++]=a[j]; c[kc++]=a[j+]; }
else if(a[j].w < a[j+].w) { a[j+].s++; b[kb++]=a[j+]; c[kc++]=a[j]; }
else
{
c[kc++]=a[j]; c[kc++]=a[j+];
}
} ib=ic=;
for(j=;ib<kb||ic<kc;j++)//一轮比赛完成以后,做一次归并操作使得a[]按积分降序排序
{
if(ic>=kc || (ib<kb&&b[ib].s>c[ic].s)||(ib<kb&&b[ib].s==c[ic].s&&b[ib].ID<c[ic].ID)) a[j]=b[ib++];
else a[j]=c[ic++];
}
}
printf("%d\n",a[Q-].ID);
free(a);
return ;
}
NOIP2011普及组 瑞士轮的更多相关文章
- [NOIP2011普及组]瑞士轮 JAVA实现
题目描述 2*N名编号为1~2N的选手共进行R轮比赛.每轮比赛开始前,以及所有比赛结束后,都会按照总分从高到低对选手进行一次排名.选手的总分为第一轮开始前的初始分数加上已参加过的所有比赛的得分和.总分 ...
- NOIP2011普及组 瑞士环 保序性
题目链接:http://noi.openjudge.cn/ch0401/4363/ 分析:如果直接模拟,时间复杂度是O(r*nlogn)超时 然后我们发现每次一轮开始时,刚开始是保序的,然后我们可以把 ...
- NOIP2011 普及组 T3 洛谷P1309 瑞士轮
今天题做太少,放道小题凑数233 题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公 ...
- [NOIP2011] 普及组
数字反转 小模拟 #include<cstdio> #include<iostream> #include<cstring> using namespace std ...
- NOIP2011普及组 数字反转
题目OJ链接: http://codevs.cn/problem/1130/ https://www.luogu.org/problemnew/show/P1307 2011年NOIP全国联赛普及组 ...
- 【解题报告】瑞士轮(NOIP2011普及组T3)
[题外话:这道题吧……说实话我不太喜欢……因为卡快排.] 题目不贴了,就是给你一个赛制,然后各个选手的初始得分和能力值,问你进行R轮比赛之后第Q名的编号是多少(这个编号读进来就要算OYZ,初始快排的时 ...
- 【单调队列】Vijos P1771 瑞士轮 (NOIP2011普及组第三题)
题目链接: https://vijos.org/p/1771 题目大意: 给定2N个人(N<=100 000)和其初始分数.能力值(能力两两不同),比赛M次(M<=50),每次PK都是按分 ...
- noip2011普及组——统计单词数
统计单词数 时间限制:1 s 内存限制:128MB [问题描述]一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数.现在,请你编程实 ...
- noip2011普及组——数字反转
数字反转 时间限制:1s 内存限制:128MB[问题描述]给定一个整数,请将该数各个位上数字反转得到一个新数.新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零 ...
随机推荐
- POJ 2352 Stars【树状数组】
<题目链接> 题目大意: 题目给出n个点,这些点按照y坐标的升序,若y相同,则按照x的升序顺序输入,问,在这些点中,左下角的点的数量分别在0~n-1的点分别有多少个,写出它们的对应点数. ...
- hexo博客pure主题解决不蒜子计数不显示的问题
最近在建个人博客网站,想统计自己的博客页面访问量,就用到了不蒜子页面访问统计.可是遇到了糟心事,居然不显示!!! 不蒜子官网示例:两行代码,搞定计数 <script async src=&quo ...
- 大数据技术 - 通俗理解MapReduce之WordCount(二)
上一章我们搭建了分布式的 Hadoop 集群.本章我们介绍 Hadoop 框架中的一个核心模块 - MapReduce.MapReduce 是并行计算模块,顾名思义,它包含两个主要的阶段,map 阶段 ...
- logback中logger详解
前言 logback实践笔记 上一篇主要对root进行了实践总结,现在基于上一篇中的springboot代码环境对logback.xml中的logger来进行实践和自己遇到的坑. logger简介 ...
- 用户不在sudoers文件中,此事将被报告
在给Virtual Box搭配共享文件夹后,普通用户使用sudo时,报错XX不在sudoers文件中.此事将被报告 然后我就按照网上教程,不巧的是正好用错误的教程修改了sudoers文件,造成root ...
- Jenkins不同job之间传递参数
有的时候不同job直接需要传递一个文件名或者路径,这个时候我们不需要传递文件实体,那这个路径如何传递呢?比如有如下两个项目,我想把A的工作目录传递给B,让B使用. A job配置 首先需要安装一个Pa ...
- 1490 ACM 数学
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1490 题意: 给出n*n 的矩阵,选出不同行不同列的n个元素,并求和: 如果所有选法所产生的和相等,则输出 ...
- python基础一 ------"有序"的字典
"有序"字典:按照写入字典的先后顺序排序的字典(比list优点是按键查询) #-*-coding:utf-8 -*- #"有序"字典:按照写入字典的先后顺序排序 ...
- [USACO08JAN]牛大赛Cow Contest
OJ题号:洛谷2419 思路: Floyd求有向图的传递闭包,只要该点与其他所有点相连即可确定名次. #include<cstdio> #include<cstring> in ...
- Java 动态代理 Demo
相比于静态代理,动态代理避免了开发者编写各个繁锁的静态代理类,只需指定一组接口及目标类对象就能动态地获取代理对象. 使用动态代理的六大步骤: 1 通过实现InvocationHandler接口来自定义 ...