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最大可以取到,R=50,單純計算不會超過,接近,在常數稍微大一點的時候確實有超時的可能。
思路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;
}