题目来自网上(2333)
乍眼一看这道题好像很水,其实——的确很水。这其实只是一道普及组的题目而已啦。但我能一遍过还是很开森的。
暴力的话,每次处理完就sort一次,感觉很不错。但根据官方的数据这只有50分,因为复杂度是O(Rnlogn)的(n是2倍N)。
其实在心里想想就能想通,每次比赛总是排名相邻的两人比赛,赢着加分,输者不加不减。我们先sort一次,然后每次把选手分为两组——胜者组和败者组。我们就可以发现,两组的分数顺序还是有序的。恍然大悟!——归并排序!
于是就手打一遍,模拟胜负,记录,归并,循环R次即可。由于数据比较大,建议开读入优化。
下面标程双手奉上(写的有点丑):
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int N,n,R,Q,win[100001],lose[100001],wini,losei,ki;
struct node
{
int s,w,num;
}f[200001],k[200001];
bool cmp(node a,node b)
{
return a.s>b.s ||(a.s==b.s && a.num<b.num);
}
int gi()
{
int x=0;char ch=getchar();
while(ch<'0' || ch>'9')ch=getchar();
while(ch>='0' && ch<='9')x=x*10+ch-48,ch=getchar();
return x;
}
int main()
{
N=gi();n=N*2;R=gi();Q=gi();
for(int t=1;t<=n;t++)
{
f[t].s=gi();
f[t].num=t;
}
for(int t=1;t<=n;t++)
{
f[t].w=gi();
}
sort(f+1,f+n+1,cmp);
while(R--)
{
wini=losei=1;
for(int tt=1;tt<=n;tt+=2)
{
if(f[tt].w>f[tt+1].w)f[tt].s+=1,win[wini++]=tt,lose[losei++]=tt+1;
else f[tt+1].s+=1,win[wini++]=tt+1,lose[losei++]=tt;
}
wini=losei=ki=1;
while(wini<=N && losei<=N)
{
if((f[win[wini]].s>f[lose[losei]].s) || (f[win[wini]].s==f[lose[losei]].s && f[win[wini]].num<f[lose[losei]].num))
k[ki++]=f[win[wini++]];
else k[ki++]=f[lose[losei++]];
}
while(wini<=N)
k[ki++]=f[win[wini++]];
while(losei<=N)
k[ki++]=f[lose[losei++]];
for(int ii=1;ii<=n;ii++)
f[ii]=k[ii];
}
printf("%d",f[Q].num);
return 0;
}
如上。