P1309 [NOIP2011 普及组] 瑞士轮 题解

P1309 [NOIP2011 普及组] 瑞士轮

题目大意:

 for  ( i <=r  ) 
      让这2n个选手的成绩降序排序,第1-第2打,第3-第4打, ...... , 第2n-1和第2n打

i --i+1 打,谁能打赢?谁的实力大谁就打赢了
排序最快是2nlogn ,所以上述暴力过程,时间复杂度是:R(2nlog2n + 2n ) =2e8超时了
解释:为什么是2n ,因为有2n个人

所以,暴力代码就出来了 ,你可以先打出暴力(要学会打暴力)

    cin >> n >> r >> q   ;
    n *= 2  ;
    for ( int i = 1 ; i <=n ; i ++ )
        cin >> a[ i ].s, a[ i ].id = i   ;
    for ( int i = 1 ; i <= n ; i ++ )
        cin >> a[ i ].w   ;

    for( int i = 1 ; i <= r ; i ++ )
    {
        sort ( a +1, a+ 1 + n, cmp ) ;
        for ( int   j = 1 ; j <= n ; j += 2  )
        {
            if ( a[ j ].w > a[ j + 1 ].w )     a[ j ].s ++ ;
            else    a[ j + 1 ].s ++ ;
        }
    }
      sort ( a +1, a+ 1 + n, cmp ) ;
    cout << a[ q ].id ;

暴力分还比较可观, 80,超俩点

怎么优化?看时间花哪里了,----排序上,所以能不能不要每次都排序,可以的
你看,1-2 , 3-4 ,2n-1---2n,他们开打的时候是有序的
打完后,你把所有的赢家拿出来放到win[]里,你想想这些赢家是不是还是有序的,咱们本来就是有序的嘛,所有的赢家每个值都+1,那不是还是有序的
你再把所有的输家拿出来放到Lsot[]里,是不是所有的输家拿出来后也是一个有序的?
所以问题就可以变成: 把两个有序的数组合并成一个有序的数组---归并排序的并的过程---O(n),好了,时间降下来了,时间复杂度可以做到R*(2n+2n)=2e7,安全了
你能去AC吗?不要往后看,如果你实在AC出错了,你再往后看,养成独立写代码的习惯

AC代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10 ;
struct node
{
    int  id , s , w ;
};
node a[ N ] ;

int n , r ,q   ;
bool cmp ( node x , node y )
{
    if ( x.s != y.s )
        return  x.s > y.s ;
    return  x.id < y.id   ;
}
int main( )
{
    cin >> n >> r >> q   ;
    n *= 2  ;
    for ( int i = 1 ;i <=n ; i ++ ) cin >> a[ i ].s , a[ i ].id = i   ;
    for ( int i = 1 ; i <= n ; i ++ ) cin >> a[ i ].w   ;
    sort ( a +1 , a+ 1 + n , cmp ) ;
    for( int i = 1 ; i <= r ; i ++ )
    {  vector <node> win , lost  ;
        for ( int   j = 1 ; j <= n ; j += 2  )
        {
            if ( a[ j ].w > a[ j + 1 ].w )
            {
                a[ j ].s ++ ;
                 win.push_back ( a[ j ] )  ;
                 lost.push_back ( a[ j + 1 ] ) ;
            }
            else
             {
                 a[ j + 1 ].s ++ ;
                  win.push_back ( a[ j + 1 ] )  ;
                  lost.push_back ( a[ j ] ) ;
             }
        }

        int  k = 1 , d = 0 , x = 0  ;
        while ( d <win.size ( ) && x < lost.size ( ) )
        {
            if ( cmp ( win[ d ] ,lost [ x ] ) )
                a[ k ++ ] = win[ d ++ ] ;
            else  a[ k ++ ] = lost[ x ++ ] ;
        }
        while ( d < win.size ( ) ) a[ k ++ ] = win[ d ++ ] ;
        while ( x < lost.size ( ) ) a[ k ++] = lost[ x ++ ] ;

    }
    cout << a[ q ].id ;
    return   0  ;
}
posted @ 2025-01-03 23:32  buyan00  阅读(79)  评论(0)    收藏  举报