当前位置:网站首页>信息学奥赛一本通 1955:【11NOIP普及组】瑞士轮 | OpenJudge 4.1 4363:瑞士轮 | 洛谷 P1309 [NOIP2011 普及组] 瑞士轮
信息学奥赛一本通 1955:【11NOIP普及组】瑞士轮 | OpenJudge 4.1 4363:瑞士轮 | 洛谷 P1309 [NOIP2011 普及组] 瑞士轮
2022-04-23 04:49:00 【君义_noip】
【题目链接】
ybt 1955:【11NOIP普及组】瑞士轮
OpenJudge 4.1 4363:瑞士轮
洛谷 P1309 [NOIP2011 普及组] 瑞士轮
【题目考点】
1. 归并排序
2. stl 排序相关函数
- stl:快速排序:
sort(f1,l1,cmp);
f1: stl容器起始迭代器,或数组第1个元素的指针。
l1:stl容器末尾迭代器,或数组最后一个元素后一个位置的指针。
cmp:比较函数
bool cmp(a,b)
参数a与b的类型必须是容器内元素的类型或数组中元素的类型。
返回值为真,则元素a排在前面。返回值为假,则元素b排在前面。 - stl合并有序序列
merge(f1, l1, f2, l2, r, cmp)
f1, l1:容器1的起始与末尾迭代器,或数组1的第一个与最后一个元素后一个位置的指针。
f2, l2:容器2的起始与末尾迭代器,或数组2的第一个与最后一个元素后一个位置的指针。
r:存放结果的容器的起始迭代器,或存放结果的数组的第一个元素的指针
cmp:比较函数
bool cmp(a,b)
参数a与b的类型必须是容器内元素的类型或数组中元素的类型。
返回值为真,则元素a排在前面。返回值为假,则元素b排在前面。
【解题思路】
直接思路:每次用sort函数排序,排名相邻的选手比赛,修改分数后继续排序。该算法需要进行 r r r次排序,每次排序的复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),题目中r能达到50,元素个数为题目中n的二倍,能达到 2 ∗ 1 0 5 2*10^5 2∗105,所以整体复杂度量级为 r ∗ n ∗ l o g 2 n = 50 ∗ 2 ∗ 1 0 5 ∗ l o g 2 ( 2 ∗ 1 0 5 ) = 1 0 7 ( l o g 2 2 + 5 l o g 2 10 ) ≤ 1 0 7 ( l o g 2 2 + 5 l o g 2 16 ) = 2.1 ∗ 1 0 8 r*n*log_2{n}=50*2*10^5*log_2{(2*10^5)}=10^7(log_2{2}+5log_2{10})\le10^7(log_2{2}+5log_2{16})=2.1*10^8 r∗n∗log2n=50∗2∗105∗log2(2∗105)=107(log22+5log210)≤107(log22+5log216)=2.1∗108,不出意外的话一定会超时的。因此这一直接的思路是不行的。
解法1:合并有序序列(归并)
第一次排序后,排名相邻的两选手之间比赛。胜方加1分,负方加0分。考察各选手得分的规律。
记 s i s_i si为第i名选手的分数, s i w s_{iw} siw为第i名选手与第i+1名选手比赛中胜者的分数, s i l s_{il} sil为败者的分数。
按分数排序后,取任意两组要进行比赛的选手,第 i i i名与第 i + 1 i+1 i+1名比赛,第 j j j名与第 j + 1 j+1 j+1名比赛,且 i + 1 < j i+1<j i+1<j,那么一定有: s i ≥ s i + 1 ≥ s j ≥ s j + 1 s_i \ge s_{i+1} \ge s_j \ge s_{j+1} si≥si+1≥sj≥sj+1
现在第 i i i名与第 i + 1 i+1 i+1名进行比赛
- 如果第 i i i名选手获胜,则 s i w = s i + 1 , s i l = s i + 1 s_{iw}=s_i+1,s_{il}=s_{i+1} siw=si+1,sil=si+1。
- 如果第 i + 1 i+1 i+1名选手获胜,则 s i w = s i + 1 + 1 , s i l = s i s_{iw}=s_{i+1}+1,s_{il}=s_{i} siw=si+1+1,sil=si
第 j j j名与第 j + 1 j+1 j+1名进行比赛
- 如果第 j j j名选手获胜,则 s j w = s j + 1 , s j l = s j + 1 s_{jw}=s_j+1,s_{jl}=s_{j+1} sjw=sj+1,sjl=sj+1。
- 如果第 j + 1 j+1 j+1名选手获胜,则 s j w = s j + 1 + 1 , s j l = s j s_{jw}=s_{j+1}+1,s_{jl}=s_{j} sjw=sj+1+1,sjl=sj
可以看出,无论是何种情况,总是有 s i w ≥ s j w s_{iw}\ge s_{jw} siw≥sjw且 s i l ≥ s j l s_{il}\ge s_{jl} sil≥sjl
即,每次比赛后的获胜方的分数为降序序列,失败方的分数也是降序序列。
考虑到分数相等时比较编号,也会有相同的结论。
接下来就是将两个有序序列合并为一个有序序列的过程。
这一方法在归并排序中有使用,合并有序序列的复杂度为 O ( n ) O(n) O(n)
具体写代码时:
写法1:可以将胜方与败方分别放入两个数组,而后合并有序序列。
写法2:数组下标奇数保存胜方,下标偶数保存败方。
使用该算法完成该题,需要循环r次,每次合并有序数组,复杂度为 O ( r ∗ n ) O(r*n) O(r∗n), r ∗ n = 50 ∗ 2 ∗ 1 0 5 = 1 0 7 r*n=50*2*10^5=10^7 r∗n=50∗2∗105=107,可以通过。
【题解代码】
解法:合并有序序列(归并)
写法1:将胜方与败方分别放入两个数组,而后合并有序序列。
- 手写合并有序序列
#include <bits/stdc++.h>
using namespace std;
#define N 200005
struct Per//选手
{
int i, s, w;//i:编号 s:分数 w:实力
}a[N], w[N], l[N];//a:所有数据 w:胜者组 l:败者组
int n, r, q;
bool cmp(Per a, Per b)
{
if(a.s == b.s)
return a.i < b.i;//分数相等 编号小的在前
else
return a.s > b.s;//分数高的排在前
}
void merge()//合并有序序列w与l
{
int i = 1, j = 1, ai = 1;
while(i <= n && j <= n)
{
if(cmp(w[i], l[j]))//如果w[i]比l[j]优先
a[ai++] = w[i++];
else
a[ai++] = l[j++];
}
while(i <= n)
a[ai++] = w[i++];
while(j <= n)
a[ai++] = l[j++];
}
int main()
{
scanf("%d %d %d", &n, &r, &q);
for(int i = 1; i <= 2*n; ++i)
{
scanf("%d", &a[i].s);
a[i].i = i;//设置编号
}
for(int i = 1; i <= 2*n; ++i)
scanf("%d", &a[i].w);
sort(a+1, a+1+2*n, cmp);
while(r--)
{
for(int i = 1; i <= n; i++)
{
if(a[2*i].w > a[2*i-1].w)//2*i与2*i-1进行一场比赛
{
a[2*i].s++;
w[i] = a[2*i];
l[i] = a[2*i-1];
}
else
{
a[2*i-1].s++;
w[i] = a[2*i-1];
l[i] = a[2*i];
}
}
merge();
}
printf("%d", a[q].i);
return 0;
}
- 使用stl merge函数
#include <bits/stdc++.h>
using namespace std;
#define N 200005
struct Per//选手
{
int i, s, w;//i:编号 s:分数 w:实力
}a[N], w[N], l[N];//a:所有数据 w:胜者组 l:败者组
int n, r, q;
bool cmp(Per a, Per b)
{
if(a.s == b.s)
return a.i < b.i;//分数相等 编号小的在前
else
return a.s > b.s;//分数高的排在前
}
int main()
{
scanf("%d %d %d", &n, &r, &q);
for(int i = 1; i <= 2*n; ++i)
{
scanf("%d", &a[i].s);
a[i].i = i;//设置编号
}
for(int i = 1; i <= 2*n; ++i)
scanf("%d", &a[i].w);
sort(a+1, a+1+2*n, cmp);
while(r--)
{
for(int i = 1; i <= n; i++)
{
if(a[2*i].w > a[2*i-1].w)//2*i与2*i-1进行一场比赛
{
a[2*i].s++;
w[i] = a[2*i];
l[i] = a[2*i-1];
}
else
{
a[2*i-1].s++;
w[i] = a[2*i-1];
l[i] = a[2*i];
}
}
merge(w+1, w+1+n, l+1, l+1+n, a+1, cmp);//stl merge函数 合并有序序列
}
printf("%d", a[q].i);
return 0;
}
写法2:数组下标奇数保存胜方,下标偶数保存败方
#include <bits/stdc++.h>
using namespace std;
#define N 200005
struct Per//选手
{
int i, s, w;//i:编号 s:分数 w:实力
}a[N], t[N];
int n, r, q;
bool cmp(Per a, Per b)
{
if(a.s == b.s)
return a.i < b.i;//分数相等 编号小的在前
else
return a.s > b.s;//分数高的排在前
}
int main()
{
scanf("%d %d %d", &n, &r, &q);
for(int i = 1; i <= 2*n; ++i)
{
scanf("%d", &a[i].s);
a[i].i = i;//设置编号
}
for(int i = 1; i <= 2*n; ++i)
scanf("%d", &a[i].w);
sort(a+1, a+1+2*n, cmp);
while(r--)
{
for(int i = 1; i < 2*n; i += 2)
{
if(a[i].w > a[i+1].w)//i与i+1进行一场比赛
a[i].s++;
else
{
a[i+1].s++;
swap(a[i], a[i+1]);//使胜者的下标为奇数
}
}
int i = 1, j = 2, ti = 1;
while(i <= 2*n-1 && j <= 2*n)//合并下标为奇数的部分与下标为偶数的部分
{
if(cmp(a[i], a[j]))
{
t[ti++] = a[i];
i += 2;
}
else
{
t[ti++] = a[j];
j += 2;
}
}
while(i <= 2*n-1)
{
t[ti++] = a[i];
i += 2;
}
while(j <= 2*n)
{
t[ti++] = a[j];
j += 2;
}
for(int i = 1; i <= 2*n; ++i)
a[i] = t[i];
}
printf("%d", a[q].i);
return 0;
}
版权声明
本文为[君义_noip]所创,转载请带上原文链接,感谢
https://blog.csdn.net/lq1990717/article/details/124356987
边栏推荐
- 敏捷实践 | 提高小组可预测性的敏捷指标
- JS generates a specified number of characters according to some words
- io. Platform. packageRoot; // ignore: deprecated_ Member_ use
- Agile practice | agile indicators to improve group predictability
- Innovative practice of short video content understanding and generation technology in meituan
- MySQL queries users logged in for at least N consecutive days
- The unity camera rotates with the mouse
- L2-011 玩转二叉树(建树+BFS)
- QML advanced (V) - realize all kinds of cool special effects through particle simulation system
- Mysql50 basic exercises
猜你喜欢
Shanghai Hangxin technology sharing 𞓜 overview of safety characteristics of acm32 MCU
QML advanced (V) - realize all kinds of cool special effects through particle simulation system
Small volume Schottky diode compatible with nsr20f30nxt5g
C language: Advanced pointer
Leetcode 1547: minimum cost of cutting sticks
Innovation training (IX) integration
PIP3 installation requests Library - the most complete pit sorting
CLion+OpenCV identify ID number - detect ID number
Solve valueerror: argument must be a deny tensor: 0 - got shape [198602], but wanted [198602, 16]
Windows remote connection to redis
随机推荐
PHP 统计指定文件夹下文件的数量
Alibaba tip: it is better to create threads manually
Unity3d practical skills - theoretical knowledge base (I)
Windows remote connection to redis
Pixel mobile phone brick rescue tutorial
Key points of AWS eks deployment and differences between console and eksctl creation
Recommended scheme for national production of electronic components of wireless keyboard
What is a data island? Why is there still a data island in 2022?
Innovation training (V) configuration information
Spark small case - RDD, broadcast
Customize the navigation bar at the top of wechat applet (adaptive wechat capsule button, flex layout)
List&lt; Map&gt; Replication: light copy and deep copy
L2-011 玩转二叉树(建树+BFS)
What is a blocking queue? What is the implementation principle of blocking queue? How to use blocking queue to implement producer consumer model?
Learning Android II from scratch - activity
【数据库】MySQL单表查询
Gets all dates between two times
DIY 一个 Excel 版的子网计算器
用LCR表完美测试无线充电系统中的线圈
What's the difference between error and exception