做題思路(錯解):拿到這道題時,想法比較簡單,直接枚舉,每進行一輪比賽,將選手的得分更新,並用sort按選手的得分由大到小(得分相同,按編號由小到大)排序,最後直接輸出答案。因爲感覺要超時,所以用了手工輸入,結果最後還是對於大的數據超時了。這種算法的時間複雜度爲O(R*2*N*log2N),很明顯當所有數據取最大值時,會超時。
解題思路(正解):本題的正解是運用分治算法的歸併排序,在輸入後先用sort排序一次,然後,每進行一輪比賽,進行一次歸併排序,歸併排序時,將贏的選手得分加1,並放入win數組(結構體),將輸的選手放入lose數組(結構體),然後就直接將win和lose數組歸併進原數組中,最後輸出答案即可。這種算法的時間複雜度爲O(R*2*N),不會超時。需要注意的是,在歸併排序時,要注意選手得分相同時,將編號小的排在前面。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=200005;
int N,R,Q;
struct data
{
int s,w,id;
};
data a[maxn],win[maxn],lose[maxn];
bool cmp(data aa,data bb)
{
if(aa.s!=bb.s) return aa.s>bb.s;
else return aa.id<bb.id;
}
void _read1(int i) //手工輸入
{
char ch=getchar();
while(ch<'0' || ch>'9') ch=getchar();
int x=0;
while(ch>='0' && ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
a[i].s=x;
}
void _read2(int i)
{
char ch=getchar();
while(ch<'0' || ch>'9') ch=getchar();
int x=0;
while(ch>='0' && ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
a[i].w=x;
}
void merge_sort()
{
int i1=1,i2=1;
for(int i=1;i<2*N;i=i+2) //計算該輪比賽後選手的得分,並轉存至win和lose數組(結構體)中
{
if(a[i].w>a[i+1].w)
{
a[i].s++;
win[i1++]=a[i];
lose[i2++]=a[i+1];
}
if(a[i].w<a[i+1].w)
{
a[i+1].s++;
win[i1++]=a[i+1];
lose[i2++]=a[i];
}
}
int i=1,j=1,k=1; //歸併排序
while(i<i1 && j<i2)
{
if(cmp(win[i],lose[j])) //注意判斷得分相同時,編號小的排在前面
{
a[k++]=win[i++];
}
else
{
a[k++]=lose[j++];
}
}
while(i<i1) a[k++]=win[i++];
while(j<i2) a[k++]=lose[j++];
}
int main()
{
//freopen("swiss.in","r",stdin);
//freopen("swiss.out","w",stdout);
scanf("%d%d%d",&N,&R,&Q);
for(int i=1;i<=2*N;i++)
{
_read1(i);
a[i].id=i;
}
for(int i=1;i<=2*N;i++)
_read2(i);
sort(a+1,a+1+2*N,cmp); //按每位選手的總分由大到小排序,總分相同的按編號由小到大排序
for(int i=1;i<=R;i++) //一共進行R輪比賽
{
merge_sort();
}
printf("%d\n",a[Q].id);
return 0;
}