NOIP2011瑞士轮

来源:互联网 发布:知乎 描写河流 编辑:程序博客网 时间:2024/04/28 06:53

题目来自网上(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;}
如上。

1 0
原创粉丝点击