【洛谷P1309】瑞士輪

P1309瑞士輪

本題同樣是NOIP普及組第三題。
因爲太久沒有做過題目了,先從普及組開始練習吧。
題目內容

思路1

很顯然想到的思路就是模擬,代碼如下:

#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
using namespace std;

struct Player{
    int id;
    int score;
    int weight;
    bool operator< (const Player& player)
    {
        return this->weight<player.weight;
    }
};

bool cmp(Player a,Player b)
{
    if(a.score!=b.score)
    {
        return a.score>b.score;
    }
    else
    {
        return a.id<b.id;
    }
}

int main(void)
{
    int n,r,q;
    cin>>n>>r>>q;
    vector<Player> player(2*n);
    for(int i = 0;i<2*n;i++)
    {
        player[i].id=i+1;
        cin>>player[i].score;
    }
    for(int i = 0;i<2*n;i++)
    {
        cin>>player[i].weight;
    }
    sort(player.begin(),player.end(),cmp);//按初始成績排序

    for(int i=0;i<r;i++)//r輪比賽
    {
        for(int j=0;j<n;j++)
        {
            if(player[2*j].weight>player[2*j+1].weight)
            {
                player[2*j].score+=1;
            }
            else
            {
                player[2*j+1].score+=1;
            }
        }
        sort(player.begin(),player.end(),cmp);

    }
    cout<<player[q-1].id<<endl;
    return 0;
}

只有60分,有4個點超時了。
分析一下算法,因爲要對R輪比賽的N次比較都進行計算,再進行一次快排,所以時間複雜度大約爲O(r(n+nlogn))這個量級。其中N最大可以取到10510^5,R=50,單純計算不會超過5×1085\times 10^8,接近10910^9,在常數稍微大一點的時候確實有超時的可能。

思路2

顯然可以發現,快排是毫無必要的,因爲分數的變動最多隻會導致鄰近順位的變化。
題解中有個思路很好,兩者相比,勝者入隊A,負者入隊B,再將AB兩隊歸併。顯然,歸併的時間複雜度爲O(n),略微優於快排的O(nlogn)

#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
using namespace std;

struct Player{
    int id;
    int score;
    int weight;
    bool operator< (const Player& player) const
    {
        if(this->score!=player.score)
        {
            return this->score<player.score;
        }
        else
        {
            return this->id>player.id;
        }
    }
    bool operator> (const Player& player) const
    {
        if(this->score!=player.score)
        {
            return this->score>player.score;
        }
        else
        {
            return this->id<player.id;
        }
    }
    Player& operator=(const Player& player)
    {
        this->id = player.id;
        this->score = player.score;
        this->weight = player.weight;
        return *this;
    }
};

bool cmp(Player a,Player b)
{
    if(a.score!=b.score)
    {
        return a.score>b.score;
    }
    else
    {
        return a.id<b.id;
    }
}

int main(void)
{
    int n,r,q;
    cin>>n>>r>>q;
    vector<Player> player(2*n);
    for(int i = 0;i<2*n;i++)
    {
        player[i].id=i+1;
        cin>>player[i].score;
    }
    for(int i = 0;i<2*n;i++)
    {
        cin>>player[i].weight;
    }
    sort(player.begin(),player.end(),cmp);//按初始成績排序

    for(int i=0;i<r;i++)//r輪比賽
    {
        vector<Player> win,lose;
        for(int j=0;j<n;j++)
        {
            if(player[2*j].weight>player[2*j+1].weight)
            {
                player[2*j].score+=1;
                win.push_back(player[2*j]);
                lose.push_back(player[2*j+1]);
            }
            else
            {
                player[2*j+1].score+=1;
                win.push_back(player[2*j+1]);
                lose.push_back(player[2*j]);
            }
        }
        //歸併
        int k=0,k1=0,k2=0;
        while(k1<n&&k2<n)
        {
            if(win[k1]>lose[k2])
            {
                player[k]=win[k1];
                k++,k1++;
            }
            else
            {
                player[k]=lose[k2];
                k++,k2++;
            }
        }
        while(k1<n)
        {
            player[k]=win[k1];
            k++,k1++;
        }
        while(k2<n)
        {
            player[k]=lose[k2];
            k++,k2++;
        }
    }
    cout<<player[q-1].id<<endl;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章