这道题我们输入后,先排一遍序,然后每个进行对比,其中要注意排序的规则,如下:
bool cmp(int x,int y){
if(grade[x]==grade[y]) return x<y;
return grade[x]>grade[y];
}
那这道题有这么简单的吗?当然没有,sort
函数无论是否是正确顺序都要进行操作,浪费了大量时间,所以做出来就只有60分,所以我们要选择一种时间复杂度更低的算法——归并排序,当然这里有人就会问了:两种方法的复杂度不都是O(nlogn)吗?
当然,复杂度都是一样大的,但是对于已经排好的数据,归并排序并不会进行操作,所以比较省时。
我们需要将赢了的人和输了的人分为两组,再逐个比较,最后将序号重新赋值回去,下面是代码:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int n,r,q,a[200100],
power[200100],grade[200100],
win[200100],lose[200100];
bool cmp(int x,int y){
if(grade[x]==grade[y]) return x<y;
return grade[x]>grade[y];
}
void Merge()
{
int i,j;
i=j=1;
a[0]=0;
while(i<=win[0]&&j<=lose[0])
if(cmp(win[i],lose[j]))
a[++a[0]]=win[i++];
else
a[++a[0]]=lose[j++];
while(i<=win[0]) a[++a[0]]=win[i++];
while(j<=lose[0]) a[++a[0]]=lose[j++];
}
int main()
{
cin>>n>>r>>q;
n*=2;
for(int i=1;i<=n;i++) a[i]=i;
for(int i=1;i<=n;i++)
scanf("%d",&grade[i]);
for(int i=1;i<=n;i++)
scanf("%d",&power[i]);
sort(a+1,a+n+1,cmp); //注意要先排一次序
for(int i=1;i<=r;i++)
{
win[0]=lose[0]=0;
for(int j=1;j<=n;j+=2)
if(power[a[j]]>power[a[j+1]]){
grade[a[j]]++;
win[++win[0]]=a[j];
lose[++lose[0]]=a[j+1];
}
else{
grade[a[j+1]]++;
win[++win[0]]=a[j+1];
lose[++lose[0]]=a[j];
}
Merge();
}
cout<<a[q];
return 0;
}