传送门
解题思路
首先想暴力做法:
每一次比赛前都sort一遍,然后两两比较,总复杂度为O(R*(n+2n*log(2n))),最大约为1.5*10^8,而且会跑满,所以需要优化。
怎么优化呢?
我们发现这样一条性质:
假设排好序的序列为1,2,3,4(1>2>3>4)。这时进行比赛(1和2,3和4),假设1,4胜利,那么很显然,胜利后的积分1一定仍然>4,2一定仍然大于3。
所以我们把它放到这道题中,用两个队列(普通队列),一个顺序存放每一轮比赛中胜利的队伍,一个顺序存放每一轮比赛中失败的队伍,很显然,这两个队列里的队伍积分是单调的。
然后就可以利用归并排序中的归并操作,把它们归并到一个数组里,继续进行下一轮比赛。
这样总复杂度为O(R*n),优化掉了一个log。
AC代码
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<queue> 5 using namespace std; 6 const int maxn=200005; 7 int n,r,q; 8 struct node{ 9 int id,value,shili; 10 }a[maxn]; 11 bool cmp(node a,node b){ 12 return a.value==b.value?a.id<b.id:a.value>b.value; 13 } 14 queue<node> q1,q2; 15 int main() 16 { 17 cin>>n>>r>>q; 18 for(int i=1;i<=2*n;i++) scanf("%d",&a[i].value); 19 for(int i=1;i<=2*n;i++) scanf("%d",&a[i].shili); 20 for(int i=1;i<=2*n;i++) a[i].id=i; 21 sort(a+1,a+2*n+1,cmp); 22 for(int i=1;i<=r;i++){ 23 for(int j=1;j<=n;j++){ 24 if(a[2*j-1].shili>a[2*j].shili){ 25 a[2*j-1].value++; 26 q1.push(a[2*j-1]); 27 q2.push(a[2*j]); 28 }else{ 29 a[2*j].value++; 30 q1.push(a[2*j]); 31 q2.push(a[2*j-1]); 32 } 33 } 34 int cnt=0; 35 while(!q1.empty()&&!q2.empty()){ 36 node a1=q1.front(); 37 node a2=q2.front(); 38 if(a1.value>a2.value){ 39 a[++cnt]=a1; 40 q1.pop(); 41 }else{ 42 if(a1.value==a2.value&&a1.id<a2.id) a[++cnt]=a1,q1.pop(); 43 else{ 44 a[++cnt]=a2; 45 q2.pop(); 46 } 47 } 48 } 49 while(!q1.empty()){ 50 a[++cnt]=q1.front(); 51 q1.pop(); 52 } 53 while(!q2.empty()){ 54 a[++cnt]=q2.front(); 55 q2.pop(); 56 } 57 } 58 cout<<a[q].id; 59 return 0; 60 }
//NOIP2001普及组 t3