洛谷P1309 瑞士轮
Posted 小时のblog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P1309 瑞士轮相关的知识,希望对你有一定的参考价值。
题目大意:
2*n个人,有初始的比赛分数和实力值。
每次比赛前总分从大到小排序,总分相同编号小的排在前面。
每次比赛是1和2比,3和4比,5和6比。
实力值大的获胜得1分。
每次比赛前排序确定比赛顺序。
题解:
模拟60
哎呀忘记最后一次排序
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define N 200007 using namespace std; int n,r,q,t; struct P{ int id,sc,h; }a[N]; bool cmp(P a,P b){ if(a.sc==b.sc)return a.id<b.id; return a.sc>b.sc; } int main(){ scanf("%d%d%d",&n,&r,&q);t=n;n*=2; for(int i=1;i<=n;i++){ scanf("%d",&a[i].sc); a[i].id=i; } for(int i=1;i<=n;i++)scanf("%d",&a[i].h); for(int i=1;i<=r;i++){ sort(a+1,a+n+1,cmp); for(int i=1;i<=t;i++){ if(a[2*i].h>a[2*i-1].h)a[2*i].sc++; else a[2*i-1].sc++; } } sort(a+1,a+n+1,cmp); printf("%d\n",a[q].id); return 0; }
正解:模拟+归并排序
60分做法时间复杂度是O()
sort的时间复杂度nlogn的
可以发现,在进行一轮比赛之后
胜的队伍+1,
败的队伍不变
所以胜的队伍的大小关系不变,败的队伍大小关系不变。
那么把每一轮胜的队伍和败的队伍分比放在一个数组里
像归并排序一样并起来。由于两个数组已经是有序的了,
所以排序的时间复杂度是O(n)的。
优化前O(r*nlogn+r*n),优化后O(2rn)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define N 200007 using namespace std; int n,r,q,t,win,lose; struct P{ int id,sc,h; }a[N],w[N],l[N]; bool cmp(P a,P b){ if(a.sc==b.sc)return a.id<b.id; return a.sc>b.sc; } bool Cp(int c1,int c2,int id1,int id2){ if(c1>c2)return true; if(c1==c2&&id1<id2)return true; return false; } void merge(int ll,int rr){ int l1=ll,l2=ll,k=ll; while(l1<=rr&&l2<=rr){ if(Cp(w[l1].sc,l[l2].sc,w[l1].id,l[l2].id))a[k++]=w[l1++]; else a[k++]=l[l2++]; } while(l1<=rr)a[k++]=w[l1++]; while(l2<=rr)a[k++]=l[l2++]; } int main(){ scanf("%d%d%d",&n,&r,&q);t=n;n*=2; for(int i=1;i<=n;i++){ scanf("%d",&a[i].sc); a[i].id=i; } for(int i=1;i<=n;i++)scanf("%d",&a[i].h); sort(a+1,a+n+1,cmp); for(int i=1;i<=r;i++){ win=0;lose=0; for(int j=1;j<=t;j++){ if(a[j*2].h>a[j*2-1].h)w[++win]=a[j*2],w[win].sc++,l[++lose]=a[j*2-1]; else w[++win]=a[j*2-1],w[win].sc++,l[++lose]=a[j*2]; } merge(1,t); } printf("%d\n",a[q].id); return 0; }
以上是关于洛谷P1309 瑞士轮的主要内容,如果未能解决你的问题,请参考以下文章