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. tensorflow基础架构 - 处理结构+创建一个线性回归模型+session+Variable+Placeholder

    以下仅为自己的整理记录,绝大部分参考来源:莫烦Python,建议去看原博客 一.处理结构 因为TensorFlow是采用数据流图(data flow graphs)来计算, 所以首先我们得创建一个数据 ...

  2. day 48-css-part1

    CSS(Cascading Style Sheet,层叠样式表 css是前端的优化器,如果说我们的html是把前端的大体骨架搭起来的话,那么我们的css就是在这个骨架的基础上进行修饰,使之更有立体感, ...

  3. int和intege相比

    int i = 100; Integer i1 = 100; Integer i2 = new Integer(100); system.out.println(i == i1);true syste ...

  4. HDU 1533 Going Home (最大权完美匹配)

    <题目链接> 题目大意:给你一张地图,地图上m代表人,H代表房子,现在所有人要走到房子内,且一个房子只能容纳一个人(人和房子的数量相同),人每移动一步,需要花1美元,问所有人走到房子中的最 ...

  5. POJ 2912 Rochambeau(暴力)+【带权并查集】

    <题目链接> 题目大意: n个人进行m轮剪刀石头布游戏(0<n<=500,0<=m<=2000),接下来m行形如x, y, ch的输入,ch='='表示x, y平局 ...

  6. Django2.0引入css、js、img文件

    Django2.0引入css.js.img文件 一.文件结构 二.settings.py的配置 # Static files (CSS, JavaScript, Images) # https://d ...

  7. UVA 207 PGA Tour Prize Money

    知识补充: ①:ssprintf: int sprintf(char *str, const char *format, ...) 发送格式化输出到 str 所指向的字符串. char str[80] ...

  8. 英语口语练习系列-C32-建筑-述说时间-暮秋独游曲江

    词汇-building(建筑) entertainment Olympic-sized swimming pool tennis court basketball field football pit ...

  9. 利用"SQL"语句自动生成序号的两种方式

    1.首先,我们来介绍第一种方式: ◆查询的SQL语句如下: select row_number() over (order by name) as rowid, sysobjects.[id] fro ...

  10. BZOJ2587 : [Ceoi2011]Team

    将球员按限制从大到小排序,那么最优解中每支球队都是一个连续的区间. 设$f[i]$表示前$i$大的球员成功组队时,最多能组的队伍数,$g[i]$表示此时最大人数的最小值. 那么$f[i]=\max(f ...