前往:我自己搭建的博客
题目
题解
此题要求对特殊数据定制更高效的排序方法,常规的排序算法都会超时。
此题关键在于发现数据的性质:在每轮比赛后,胜者的相对位次不变(全体分数+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;
}