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普及组 瑞士轮的更多相关文章

  1. [NOIP2011普及组]瑞士轮 JAVA实现

    题目描述 2*N名编号为1~2N的选手共进行R轮比赛.每轮比赛开始前,以及所有比赛结束后,都会按照总分从高到低对选手进行一次排名.选手的总分为第一轮开始前的初始分数加上已参加过的所有比赛的得分和.总分 ...

  2. NOIP2011普及组 瑞士环 保序性

    题目链接:http://noi.openjudge.cn/ch0401/4363/ 分析:如果直接模拟,时间复杂度是O(r*nlogn)超时 然后我们发现每次一轮开始时,刚开始是保序的,然后我们可以把 ...

  3. NOIP2011 普及组 T3 洛谷P1309 瑞士轮

    今天题做太少,放道小题凑数233 题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公 ...

  4. [NOIP2011] 普及组

    数字反转 小模拟 #include<cstdio> #include<iostream> #include<cstring> using namespace std ...

  5. NOIP2011普及组 数字反转

    题目OJ链接: http://codevs.cn/problem/1130/ https://www.luogu.org/problemnew/show/P1307 2011年NOIP全国联赛普及组 ...

  6. 【解题报告】瑞士轮(NOIP2011普及组T3)

    [题外话:这道题吧……说实话我不太喜欢……因为卡快排.] 题目不贴了,就是给你一个赛制,然后各个选手的初始得分和能力值,问你进行R轮比赛之后第Q名的编号是多少(这个编号读进来就要算OYZ,初始快排的时 ...

  7. 【单调队列】Vijos P1771 瑞士轮 (NOIP2011普及组第三题)

    题目链接: https://vijos.org/p/1771 题目大意: 给定2N个人(N<=100 000)和其初始分数.能力值(能力两两不同),比赛M次(M<=50),每次PK都是按分 ...

  8. noip2011普及组——统计单词数

    统计单词数 时间限制:1 s 内存限制:128MB [问题描述]一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数.现在,请你编程实 ...

  9. noip2011普及组——数字反转

    数字反转 时间限制:1s 内存限制:128MB[问题描述]给定一个整数,请将该数各个位上数字反转得到一个新数.新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零 ...

随机推荐

  1. day 47 htm-part2

    列表 无序列表====所谓无序就是显示出来的效果没有编号排序 <ul type='disc'> <li>第一项</li> <li>第二项</li& ...

  2. oracle的DBMS_JOB相关知识

    http://langgufu.iteye.com/blog/1179235 查看当前定时任务 select job,next_date,next_sec,failures,broken from u ...

  3. Linux上iptables防火墙的基本应用教程

    iptables是Linux上常用的防火墙软件,下面vps侦探给大家说一下iptables的安装.清除iptables规则.iptables只开放指定端口.iptables屏蔽指定ip.ip段及解封. ...

  4. UVa-156 Ananagrams 反片语【map】【vector】

    题目链接:https://vjudge.net/contest/211547#problem/D 题目大意: 输入一些单词,找出所有满足以下条件的单词:该单词不能通过字母重排,得到输入文本中的另外一些 ...

  5. DDL DML概念 --- Msysql常用命令

    一.DML DML(data manipulation language)数据操纵语言: 就是我们最经常用到的 SELECT.UPDATE.INSERT.DELETE. 主要用来对数据库的数据进行一些 ...

  6. 003.MMM双主-双从读写分离部署

    一 前期规划 1.1 主机规划 1.2 虚拟IP规划 1.3 用户列表 提示:以上角色需要在所有节点添加. 1.4 整体架构 1.4 hosts修改 1 [root@localhost ~]# vi ...

  7. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-6 直接光源采样

    Chapter7 Sample Lights Directly  Preface 今天我们来讲这个还算牛逼的技术——直接光源采样 之前我们提到过,在2-7 前两篇我们也提到要减少噪点,就是图片上的黑点 ...

  8. linux学习笔记 less命令

    空格 或者 ctrl+f  前进一屏     ctrl+b  后退一屏幕 回车 前进一行 /string                  查找含有string字符串的页 ?string        ...

  9. Socket 网络通信

    Socket 网络通信 1.OSI (Open System Interconnect Reference Model)(开放系统互联参考模型) 从下低到高 :物理层.数据链路层.网络层.传输层.会话 ...

  10. Jenkins不同job之间传递参数

    有的时候不同job直接需要传递一个文件名或者路径,这个时候我们不需要传递文件实体,那这个路径如何传递呢?比如有如下两个项目,我想把A的工作目录传递给B,让B使用. A job配置 首先需要安装一个Pa ...