【题解】洛谷P1309瑞士轮

前往:我自己搭建的博客

题目

洛谷P1309瑞士轮

题解

此题要求对特殊数据定制更高效的排序方法,常规的排序算法都会超时。

此题关键在于发现数据的性质:在每轮比赛后,胜者的相对位次不变(全体分数+1),败者的相对位次也不变。然后,就能得到两条单调的数列,只要合并即可。这项操作与归并排序中的合并操作相似。由于数据类型是struct,不方便直接进行操作(其实很方便,把tmp1[],tmp2[]都换成struct型即可),所以采用表排序(即间接排序),对数据的编号(下标)进行操作。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
int n,r,q;
int rk[maxn],tmp1[maxn],tmp2[maxn];	//rk[i]表示第i名的选手的编号(即a数组下标) 
struct athlete {int s,w;}a[maxn];
inline bool cmp(const int &x,const int &y) {return a[x].s==a[y].s ? x<y : a[x].s>a[y].s;}
inline void solve()
{
	for(int i=1;i<=r;i++)
	{
		for(int j=1;j<=n;j+=2)
		{
			//tmp1[]临时存放胜者,tmp2[]临时存放败者
			if(a[rk[j]].w>a[rk[j+1]].w) a[rk[j]].s++,tmp1[j/2+1]=rk[j],tmp2[j/2+1]=rk[j+1];
			else a[rk[j+1]].s++,tmp2[j/2+1]=rk[j],tmp1[j/2+1]=rk[j+1];
		}
		int l1=1,l2=1,cur=1;
		while(l1<=n/2&&l2<=n/2) 
		{
			if(a[tmp1[l1]].s>a[tmp2[l2]].s) rk[cur++]=tmp1[l1++];
			else if(a[tmp1[l1]].s<a[tmp2[l2]].s) rk[cur++]=tmp2[l2++];
			else tmp1[l1]<tmp2[l2] ? rk[cur++]=tmp1[l1++] : rk[cur++]=tmp2[l2++];
		}
		while(l1<=n/2) rk[cur++]=tmp1[l1++];
		while(l2<=n/2) rk[cur++]=tmp2[l2++];
	}
}
int main()
{
	scanf("%d%d%d\n",&n,&r,&q); n*=2;
	for(int i=1;i<=n;i++) scanf("%d",&a[i].s),rk[i]=i;
	for(int i=1;i<=n;i++) scanf("%d",&a[i].w);
	sort(rk+1,rk+n+1,cmp);
	solve();
	printf("%d\n",rk[q]);
	
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值