今天做到一道关于排序的题:

[NOIP2011 普及组] 瑞士轮

题目背景

在双人对决的竞技性比赛,如乒乓球、羽毛球、国际象棋中,最常见的赛制是淘汰赛和循环赛。前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高。后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长。

本题中介绍的瑞士轮赛制,因最早使用于 1895 1895 1895年在瑞士举办的国际象棋比赛而得名。它可以看作是淘汰赛与循环赛的折中,既保证了比赛的稳定性,又能使赛程不至于过长。

题目描述

2 × N 2 \times N 2×N 名编号为 1 ∼ 2 N 1\sim 2N 1∼2N 的选手共进行R 轮比赛。每轮比赛开始前,以及所有比赛结束后,都会按照总分从高到低对选手进行一次排名。选手的总分为第一轮开始前的初始分数加上已参加过的所有比赛的得分和。总分相同的,约定编号较小的选手排名靠前。

每轮比赛的对阵安排与该轮比赛开始前的排名有关:第 1 1 1 名和第 2 2 2 名、第 3 3 3 名和第 4 4 4名、……、第$2K - 1 名和第 名和第 名和第 2K$名、…… 、第$2N - 1 $名和第 2 N 2N 2N名,各进行一场比赛。每场比赛胜者得$1 $分,负者得 $0 $分。也就是说除了首轮以外,其它轮比赛的安排均不能事先确定,而是要取决于选手在之前比赛中的表现。

现给定每个选手的初始分数及其实力值,试计算在R 轮比赛过后,排名第$ Q$ 的选手编号是多少。我们假设选手的实力值两两不同,且每场比赛中实力值较高的总能获胜。

输入格式

第一行是三个正整数 N , R , Q N,R ,Q N,R,Q,每两个数之间用一个空格隔开,表示有 $2 \times N 名选手、 名选手、 名选手、R$ 轮比赛,以及我们关心的名次 Q Q Q。

第二行是 2 × N 2 \times N 2×N 个非负整数 s 1 , s 2 , … , s 2 N s_1, s_2, …, s_{2N} s1​,s2​,…,s2N​,每两个数之间用一个空格隔开,其中$ s_i 表示编号为 表示编号为 表示编号为i$ 的选手的初始分数。 第三行是 2 × N 2 \times N 2×N 个正整数 w 1 , w 2 , … , w 2 N w_1 , w_2 , …, w_{2N} w1​,w2​,…,w2N​,每两个数之间用一个空格隔开,其中 w i w_i wi​ 表示编号为 i i i 的选手的实力值。

输出格式

一个整数,即 R R R 轮比赛结束后,排名第 Q Q Q 的选手的编号。

样例 #1

样例输入 #1

2 4 2
7 6 6 7
10 5 20 15

样例输出 #1

1

提示

【样例解释】

【数据范围】

对于 30 % 30\% 30%的数据, 1 ≤ N ≤ 100 1 ≤ N ≤ 100 1≤N≤100;

对于 50 % 50\% 50%的数据, 1 ≤ N ≤ 10 , 000 1 ≤ N ≤ 10,000 1≤N≤10,000;

对于 100 % 100\% 100%的数据, 1 ≤ N ≤ 100 , 000 , 1 ≤ R ≤ 50 , 1 ≤ Q ≤ 2 N , 0 ≤ s 1 , s 2 , … , s 2 N ≤ 1 0 8 , 1 ≤ w 1 , w 2 , … , w 2 N ≤ 1 0 8 1 ≤ N ≤ 100,000,1 ≤ R ≤ 50,1 ≤ Q ≤ 2N,0 ≤ s_1, s_2, …, s_{2N}≤10^8,1 ≤w_1, w_2 , …, w_{2N}≤ 10^8 1≤N≤100,000,1≤R≤50,1≤Q≤2N,0≤s1​,s2​,…,s2N​≤108,1≤w1​,w2​,…,w2N​≤108。

noip2011普及组第3题。


  可以发现,每次比赛之后的序列的大小顺序并不是随机的,赢者和输者各自内部仍是有序的。一开始我每次循环都会用sort排序,但sort是基于快速排序,适合处理随机序列,对于题目中这种并不占优势,时间复杂度会变成 R × N l o g N R \times NlogN R×NlogN。不难想到归并排序,由于已经有两个有序子序列,接下来只要将序列归并就行了,可以省很多时间。
  注意win和lose两个数组的下标问题。


下面提供我的ac代码:

#include <bits/stdc++.h>using namespace std;#define N 2 * 1000000 + 10struct Node {int num, s, w;
}a[N], win[N], lose[N];int cnt1, cnt2;bool cmp (struct Node x, struct Node y) {if (x.s == y.s)return x.num < y.num;return x.s > y.s;
}void Merge() {int i = 0, j = 0, cnt = 0;while (i < cnt1 && j < cnt2) {if (cmp(win[i], lose[j]))a[cnt++] = win[i++];elsea[cnt++] = lose[j++];}while (i < cnt1)a[cnt++] = win[i++];while (j <cnt2)a[cnt++] = lose[j++];
}int main() {std::ios::sync_with_stdio(false);std::cin.tie(0);int n, r, q;cin >> n >> r >> q;for (int i = 0; i < 2 * n; ++i) {cin >> a[i].s;a[i].num = i + 1;}for (int i = 0; i < 2 * n; ++i)cin >> a[i].w;sort(a, a + 2 * n, cmp);while (r--) {cnt1 = 0, cnt2 = 0;for (int i = 0; i < n; ++i) {if (a[2 * i].w > a[2 * i + 1].w) {++a[2 * i].s;win[cnt1++] = a[2 * i];lose[cnt2++] = a[2 * i + 1];}else {++a[2 * i + 1].s;win[cnt1++] = a[2 * i + 1];lose[cnt2++] = a[2 * i];}}Merge();}cout << a[q - 1].num;return 0;
}

关于归并排序和快速排序相关推荐

  1. 排序算法中——归并排序和快速排序

    冒泡排序.插入排序.选择排序这三种算法的时间复杂度都为 $O(n^2)$,只适合小规模的数据.今天,我们来认识两种时间复杂度为 $O(nlogn)$ 的排序算法--归并排序(Merge Sort)和快 ...

  2. 排序算法:归并排序、快速排序

    相关博客: 排序算法:冒泡排序.插入排序.选择排序.希尔排序 排序算法:归并排序.快速排序 排序算法:桶排序.计数排序.基数排序 排序算法:堆排序 十大排序算法小结 一.归并排序: 1.工作原理: 归 ...

  3. 排序算法--(冒泡排序,插入排序,选择排序,归并排序,快速排序,桶排序,计数排序,基数排序)

    一.时间复杂度分析 - **时间复杂度**:对排序数据的总的操作次数.反应当n变化时,操作次数呈现什么规律 - **空间复杂度**:算法在计算机内执行时所需要的存储空间的容量,它也是数据规模n的函数. ...

  4. 十大排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序

    冒泡排序.选择排序.插入排序.希尔排序.归并排序.快速排序.堆排序.计数排序.桶排序.基数排序的动图与源代码. 目录 关于时间复杂度 冒泡排序 选择排序 插入排序 希尔排序 归并排序 快速排序 堆排序 ...

  5. 归并排序,快速排序为什么快

    对于一个 n n n个元素的数组,必须要确定两两之间的相对顺序,假设每次都抓取不同的二元组,需要 log ⁡ 2 n ! \log_2n! log2​n!次比较,由于 log ⁡ 2 n ! ≈ n ...

  6. 排序算法之——归并排序和快速排序

    冒泡排序.插入排序.选择排序这三种算法的时间复杂度都为 O ( n 2 ) O(n^2) O(n2),只适合小规模的数据.今天,我们来认识两种时间复杂度为 O ( n l o g n ) O(nlog ...

  7. 常见排序算法原理及实现——第二部分(归并排序、快速排序、堆排序)

    引言 排序算法第一部分,我们聊了冒泡排序.插入排序.选择排序这三种排序算法,它们的时间复杂度比较高,都是 O(n2),适合小规模数据的排序.今天,我们来看三种时间复杂度为 O(nlogn) 的排序算法 ...

  8. 适用于大规模数据排序(归并排序、快速排序)

    一.归并排序 1.1.分析 先把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了. 1.2.使用递推思路实现 ①先写出递推公式:[mergeSo ...

  9. 排序(下):归并排序和快速排序

    本文是学习算法的笔记,<数据结构与算法之美>,极客时间的课程 归并排序和快速排序,是两种时间复杂度为O(nlogn)的排序,适合大规模的排序,比上节所说的三种排序(冒泡.插入.选择)更常用 ...

  10. 归并排序、快速排序和堆排序及C代码

    排序 1.归并排序 1.1归并排序的概念 1.2算法步骤 1.3代码示例 2.快速排序 2.1快速排序的概念 2.2算法步骤 2.3代码示例 3.堆排序 3.1堆排序的概念 3.2算法步骤 3.3代码 ...

最新文章

  1. 致被套基民:老基民的四点教训七点经验(ZT)
  2. Macbook m1 install Homebrew
  3. SEO搜索引擎优化排名方法大全
  4. ZooKeeper入门(二)Java操作zookeeper
  5. u-boot_NAND_Flash操作命令及烧录Linux内核和文件系统
  6. mysql数据库字符集设置_查看和设置MySQL数据库字符集
  7. Hadoop 实践(一) 环境搭建
  8. 【转】64位ORACLE客户端上plsql无法识别ORACLE_HOME解决方案
  9. 智能优化算法:乌燕鸥优化算法-附代码
  10. cvpr 深度估计_北京航空航天大学团队在CVPR2017-4D光场深度估计竞赛中夺冠
  11. 恶意软件可以使用风扇噪音盗取数据
  12. Linux删除含有特殊符号文件名的文件
  13. 如何用公式编辑器编辑直角三角形符号
  14. android unity 瘦身,unity/unity3d编译成android apk包瘦身方法
  15. 机器学习诗词创作_通过机器学习创作音乐
  16. [eNSP]→静态路由、负载分担、备用链路
  17. Vue-cli 脚手架一
  18. 手机邮箱怎么弄_安卓手机如何接收邮件 教你安卓手机邮箱设置方法
  19. 383计算机毕业设计
  20. 清晨为何不能空腹喝蜂蜜水

热门文章

  1. TCP和UDP------报文格式
  2. 音乐网站要什么服务器,告诉你怎么样去做一个音乐网站
  3. 韦一之SI等工具使用(007课)
  4. 编程之基 --- C语言基础大全 IV
  5. 高通msm8909增加GPIO按键
  6. DNA甲基化研究概述
  7. Vue动态控制disabled属性
  8. Python攻城师的成长————面向对象的三大特征(继承、多态)
  9. 护网行动安全防守工作指南应看
  10. PostgreSQL数据库头胎——后台一等公民进程StartupDataBase 信号通知