【洛谷 P1309】 【归并排序】 瑞士轮
题目
解题思路
先快排将选手的初始得分排序
每一轮都给赢者和输者分成两个队列
给赢者加分
因为本来的序列就是降序的,所以分裂后的两个队列也是降序的
利用归并排序的思想将两个队列合并
得出每一轮结束后的排名
代码
#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
struct lzf{
int f,n,w;
}a[200010],temp[200010],win[200010],lose[200010];
int n,q,r,len1,len2;
bool cmp(lzf f,lzf t)
{
if (f.f==t.f)
return f.w<t.w;
else return f.f>t.f;
} //快排,从大到小
void merge()
{
int i=1,j=1,c=1;
while (i<=len1&&j<=len2)
{
if ((win[i].f>lose[j].f)||(win[i].f==lose[j].f&&win[i].w<lose[j].w))
a[c++]=win[i++];
else a[c++]=lose[j++];
}
while (i<=len1) a[c++]=win[i++];
while (j<=len2) a[c++]=lose[j++];
} //合并
int main()
{
scanf("%d%d%d",&n,&r,&q);
for (int i=1;i<=2*n;i++)
{
a[i].w=i;
scanf("%d",&a[i].f);
}
for (int i=1;i<=2*n;i++)
scanf("%d",&a[i].n);
sort(a+1,a+2*n+1,cmp);
for (int i=1;i<=r;i++)
{
len1=len2=0;
for (int j=1;j<=n;j++)
if (a[2*j-1].n>a[2*j].n) //加分以及分组
{
a[2*j-1].f++;
win[++len1]=a[2*j-1];
lose[++len2]=a[2*j];
}
else {
a[2*j].f++;
win[++len1]=a[2*j];
lose[++len2]=a[2*j-1];
}
merge();
}
printf("%d",a[q].w); //输出排名所对应的位置
}