当前位置:网站首页>信息学奥赛一本通 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
边栏推荐
- Flink's important basics
- The 14th issue of HMS core discovery reviews the long article | enjoy the silky clip and release the creativity of the video
- Experience summary and sharing of the first prize of 2021 National Mathematical Modeling Competition
- Innovation training (IX) integration
- Repair of self calibration SPC failure of Tektronix oscilloscope dpo3054
- leetcode002--将有符号整数的数字部分反转
- Innovation training (VII) FBV view & CBV view
- Open the past and let's start over.
- 【数据库】MySQL单表查询
- Recommended scheme of national manufactured electronic components
猜你喜欢

QML advanced (V) - realize all kinds of cool special effects through particle simulation system

Excel uses the functions of replacement, sorting and filling to comprehensively sort out financial data

C language: spoof games

Recommended scheme of national manufactured electronic components

Mysql50 basic exercises

Learning Android II from scratch - activity

New terminal play method: script guidance independent of technology stack

Flink's important basics
![[timing] empirical evaluation of general convolution and cyclic networks for sequence modeling based on TCN](/img/c5/3b3f9cf9a39bf14a68ac100294ca6c.png)
[timing] empirical evaluation of general convolution and cyclic networks for sequence modeling based on TCN

Innovation training (V) configuration information
随机推荐
Unity摄像头跟随鼠标旋转
Recommended scheme for national production of electronic components of wireless keyboard
getprop 属性
【数据库】MySQL多表查询(一)
What is a blocking queue? What is the implementation principle of blocking queue? How to use blocking queue to implement producer consumer model?
leetcode002--将有符号整数的数字部分反转
Logger and zap log Library in go language
使用model.load_state_dict()时,出现AttributeError: ‘str‘ object has no attribute ‘copy‘
Getprop property
Youqilin 22.04 lts version officially released | ukui 3.1 opens a new experience
Innovation training (VII) FBV view & CBV view
leetcode007--判断字符串中的括号是否匹配
Eksctl deploying AWS eks
KVM error: Failed to connect socket to ‘/var/run/libvirt/libvirt-sock‘
io. Platform. packageRoot; // ignore: deprecated_ Member_ use
Solve valueerror: argument must be a deny tensor: 0 - got shape [198602], but wanted [198602, 16]
Painless upgrade of pixel series
Unity camera rotation with sliding effect (rotation)
The last day of 2021 is the year of harvest.
Sword finger offer: push in and pop-up sequence of stack