【题解】洛谷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;
}

猜你喜欢

转载自blog.csdn.net/zjgmartin/article/details/108415753
今日推荐