luogu P1309 瑞士轮【排序】

题目背景

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

本题中介绍的瑞士轮赛制,因最早使用于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 的选手的编号。

输入输出样例

输入样例#1:

2 4 2
7 6 6 7
10 5 20 15

输出样例#1:

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题。

冷静分析

最暴力的肯定是每battle一次都进行一次结构体快速排序,但是太慢了,60分。

经我们冷静分析可以发现一些特殊性质,也就是说,一次battle下来,因为有之前的“积分有序性”,所以新的排名并不会有太大的变化。卡sort的情况下,我们可以考虑稳定的归并,O(nlogn);

这里使用了一种类mergesort;

注释写在代码里。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 int n,r,e;
 6 struct node
 7 {
 8     int score,pos,abi;
 9 };
10 node q[200002],win[200002],lose[200002];//win和lose保证有序。
11 bool cmp(node a,node b)
12 {
13     if(a.score==b.score) return a.pos<b.pos;
14     return a.score>b.score;
15 }
16 void merge()
17 {//类归并
18     int tmp=n/2;//注意。win和lose中元素个数各为tmp个
19     int i=1,j=1,k=1;
20     while(i<=tmp&&j<=tmp)
21     {
22         if(win[i].score>lose[j].score||(win[i].score==lose[j].score&&win[i].pos<lose[j].pos))
23         {
24             q[k]=win[i];
25             i++;k++;
26         }
27         else
28         {
29             q[k]=lose[j];
30             j++;k++;
31          }
32     }//下面的while循环,要么执行第一个,要么执行第二个,因为当 上一循环跳出时总有一条件不符合。
33     while(i<=tmp)
34     {
35         q[k]=win[i];
36         i++;k++;
37     }
38     while(j<=tmp)
39     {
40         q[k]=lose[j];
41         j++;k++;
42      }
43 }
44 int main()
45 {
46     scanf("%d%d%d",&n,&r,&e);
47     n=2*n;//小细节
48     for(int i=1;i<=n;i++)
49     {
50         scanf("%d",&q[i].score);
51         q[i].pos=i;//pos代表初始编号
52     }
53     for(int i=1;i<=n;i++) scanf("%d",&q[i].abi);
54     sort(q+1,q+n+1,cmp);
55     for(int i=1;i<=r;i++)
56     {//num在表示第几次battle,及其结果。
57         int num=0;//注意num是用于一次battle下来的,一次battle要走完下面的循环,注意定义位置。
58         for(int j=1;j<=n;j+=2)//步长加至2.
59         {
60             if(q[j].abi>q[j+1].abi)
61             {
62                 q[j].score ++;
63                 num++;
64                 win[num]=q[j];//第num个赢的人
65                 lose[num]=q[j+1];//第num个输的人
66             }
67             else
68             {
69                 q[j+1].score ++;
70                 num++;
71                 win[num]=q[j+1];
72                 lose[num]=q[j];
73             }
74         }
75         merge();//两两battle后统一排序
76     }
77     printf("%d",q[e].pos);
78     return 0;
79 }

大道至简!

原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9076351.html

时间: 2024-10-03 23:04:07

luogu P1309 瑞士轮【排序】的相关文章

P1309 瑞士轮 (吸氧了)

P1309 瑞士轮 题解 1.这题可以模拟一下 2.sort吸氧可以过(可能是排序有点慢吧,不开会T) sort排序时注意: return 1 是满足条件,不交换 return 0是不满足,交换 代码(吸氧优化了一下QWQ) // luogu-judger-enable-o2 #include<bits/stdc++.h> using namespace std; int n,r,q; struct node { int s,num,w; }peo[200002]; bool cmp(node

洛谷P1309——瑞士轮(归并排序)

https://www.luogu.org/problem/show?pid=1309#sub 题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长. 本题中介绍的瑞士轮赛制,因最早使用于1895年在瑞士举办的国际象棋比赛而得名.它可以看作是淘汰赛与循环赛的折衷,既保证了比赛的稳定性,又能使赛程不至于过长. 题目描述 2*N 名编号为 1~2N

NOIP2011 普及组 T3 洛谷P1309 瑞士轮

今天题做太少,放道小题凑数233 题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长. 本题中介绍的瑞士轮赛制,因最早使用于1895年在瑞士举办的国际象棋比赛而得名.它可以看作是淘汰赛与循环赛的折衷,既保证了比赛的稳定性,又能使赛程不至于过长. 题目描述 2*N 名编号为 1~2N 的选手共进行R 轮比赛.每轮比赛开始前,以及所有比赛结束后,都

P1309 瑞士轮 未完成 60

题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长. 本题中介绍的瑞士轮赛制,因最早使用于1895年在瑞士举办的国际象棋比赛而得名.它可以看作是淘汰赛与循环赛的折衷,既保证了比赛的稳定性,又能使赛程不至于过长. 题目描述 2*N 名编号为 1~2N 的选手共进行R 轮比赛.每轮比赛开始前,以及所有比赛结束后,都会按照总分从高到低对选手进行一次排

洛谷 P1309 瑞士轮

题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长. 本题中介绍的瑞士轮赛制,因最早使用于1895年在瑞士举办的国际象棋比赛而得名.它可以看作是淘汰赛与循环赛的折衷,既保证了比赛的稳定性,又能使赛程不至于过长. 题目描述 2*N 名编号为 1~2N 的选手共进行R 轮比赛.每轮比赛开始前,以及所有比赛结束后,都会按照总分从高到低对选手进行一次排

洛谷P1309 瑞士轮

传送门 题目大意: 2*n个人,有初始的比赛分数和实力值. 每次比赛前总分从大到小排序,总分相同编号小的排在前面. 每次比赛是1和2比,3和4比,5和6比. 实力值大的获胜得1分. 每次比赛前排序确定比赛顺序. 题解: 模拟60 哎呀忘记最后一次排序 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define N 200007 using namespac

洛谷1309 瑞士轮

本题地址:http://www.luogu.org/problem/show?pid=1309 题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长. 本题中介绍的瑞士轮赛制,因最早使用于1895年在瑞士举办的国际象棋比赛而得名.它可以看作是淘汰赛与循环赛的折衷,既保证了比赛的稳定性,又能使赛程不至于过长. 题目描述 2*N 名编号为 1~2N

[NOIP2011]瑞士轮

题目大意:要你模拟瑞士轮赛制,求出R轮后第Q名选手的编号. 解题思路:首先对所有选手按分数从大到小进行排序,然后模拟比赛. 因为原本是排好序的,赢的加1分,输的扣1分,所以赢的人和输的人也是分别有序的. 所以我们可以把每轮赢的人扔进一个数组,输的人扔进另一个数组,然后归并就行了. C++可以用algorithm里的sort()和merge()实现排序和归并. 时间复杂度O(2nR). 注意n最大100000,所以最多有200000人,开数组要开200000. C++ Code: #include

瑞士轮

本题地址:http://www.luogu.org/problem/show?pid=1309 noip2011普及组第3题. 题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长.本题中介绍的瑞士轮赛制,因最早使用于1895年在瑞士举办的国际象棋比赛而得名.它可以看作是淘汰赛与循环赛的折衷,既保证了比赛的稳定性,又能使赛程不至于过长. 题目描述