洛谷 P1309 瑞士轮 归并

本文介绍了洛谷P1309题目的瑞士轮算法,讨论了在实现过程中使用快排导致超时的问题。通过将每轮比赛后赢者和输者的序列进行归并,实现了O(n)的时间复杂度。使用vector的push_back操作导致了超时,改用new分配空间后问题解决,程序运行时间降低。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

洛谷 P1309 瑞士轮

https://www.luogu.com.cn/problem/P1309

每一轮快排,超时:

# include<iostream>
# include<fstream>
# include<vector> 
# include<algorithm> 
using namespace std;
class Athlete
{
public:
	int id,competence,score;
	Athlete(){}
	// 
	Athlete(int _id,int _competence,int _score):id(_id),competence(_competence),score(_score)
	{

	}
};

bool comp(const Athlete& _a, const Athlete& _b)
{
	if(_a.score>_b.score)
		return true;
	else if(_a.score<_b.score)
		return false;
	else
		return _a.id<_b.id;
}

int main()
{
	int N,R,Q;
//	ifstream infile("data.txt");
//	infile>>N>>R>>Q;
	cin>>N>>R>>Q;
	int* init_score_arr=new int[2*N];
	int* competence_arr=new int[2*N];
	vector<Athlete> athlete_vec;
	for(int i=0;i<2*N;++i)
		cin>>init_score_arr[i];
	for(int i=0;i<2*N;++i)
		cin>>competence_arr[i];
	for(int i=0;i<2*N;++i)
	{
		athlete_vec.push_back(Athlete(i,competence_arr[i],init_score_arr[i]));
	}
	sort(athlete_vec.begin(),athlete_vec.end(),comp);
	for(int round=0;round<R;++round)
	{
		for(int i=0;i<N;++i)
		{
			if(athlete_vec[2*i].competence<athlete_vec[2*i+1].competence)
				++athlete_vec[2*i+1].score;
			else
				++athlete_vec[2*i].score;
		}
		sort(athlete_vec.begin(),athlete_vec.end(),comp);
	}
	
	cout<<athlete_vec[Q-1].id+1<<endl;
	delete []init_score_arr;
	delete []competence_arr;
	return 0;
} 

每次比赛之后,分数按照降序排列,每两人中的赢的人都+1分,赢的N个人仍为降序,输的N个人也仍为降序,所以将赢的序列与输的序列归并即可。每轮O(n)复杂度。而快排每轮O(nlogn)。
用vector push_back出现超时,用new分配空间accepeted,应该是push_back太慢。

# include<iostream>
# include<fstream>
# include<vector> 
# include<algorithm> 
using namespace std;
class Athlete
{
public:
	int id,competence,score;
	Athlete(){}
	// 
	Athlete(int _id,int _competence,int _score):id(_id),competence(_competence),score(_score)
	{

	}
};

bool comp(const Athlete& _a, const Athlete& _b)
{
	if(_a.score>_b.score)
		return true;
	else if(_a.score<_b.score)
		return false;
	else
		return _a.id<_b.id;
}

int main()
{
	int N,R,Q;
//	ifstream infile("data.txt");
//	infile>>N>>R>>Q;
	cin>>N>>R>>Q;
	int* score_arr=new int[2*N];
	int* competence_arr=new int[2*N];
	int* rank_id_arr=new int[2*N];
	vector<Athlete> athlete_vec;
	for(int i=0;i<2*N;++i)
		cin>>score_arr[i];
	for(int i=0;i<2*N;++i)
		cin>>competence_arr[i];
	for(int i=0;i<2*N;++i)
	{
		athlete_vec.push_back(Athlete(i,competence_arr[i],score_arr[i]));
	}
	sort(athlete_vec.begin(),athlete_vec.end(),comp);
	for(int i=0;i<2*N;++i)
	{
		rank_id_arr[i]=athlete_vec[i].id;
	}
	int* winner_id_arr=new int[N];
	int* loser_id_arr=new int[N];
	for(int round=0;round<R;++round)
	{

		for(int i=0;i<N;++i)
		{
			int a_id=rank_id_arr[2*i];
			int b_id=rank_id_arr[2*i+1];
			int winner_id=-1;
			int loser_id=-1;
			if(competence_arr[a_id]<competence_arr[b_id])
			{
				++score_arr[b_id];
				winner_id=b_id;
				loser_id=a_id;
			}
			else
			{
				++score_arr[a_id];
				winner_id=a_id;
				loser_id=b_id;
			}
			winner_id_arr[i]=winner_id;
			loser_id_arr[i]=loser_id;
		}
//		printf("winner_id_vec: ");
//		for(int i=0;i<N;++i)
//			printf("%d, ",winner_id_vec[i]);
//		cout<<endl;
//		sort(athlete_vec.begin(),athlete_vec.end(),comp);
		//merge sort
		int winner_i=0;
		int loser_i=0;
		int i=0;
		while(winner_i<N&&loser_i<N)
		{
			int winner_id=winner_id_arr[winner_i];
			int loser_id=loser_id_arr[loser_i];
			int winner_score=score_arr[winner_id];
			int loser_score=score_arr[loser_id];
			bool comp_res=false;
			if(winner_score<loser_score)
				comp_res=true;
			else if(winner_score>loser_score)
				comp_res=false;
			else
				comp_res=(winner_id>loser_id);
			if(comp_res)
			{
				rank_id_arr[i]=loser_id;
				++i;
				++loser_i;
			}
			else
			{
				rank_id_arr[i]=winner_id;
				++i;
				++winner_i;
			}	
		}
		while(winner_i<N)
		{
			int winner_id=winner_id_arr[winner_i];
			rank_id_arr[i]=winner_id;
			++i;
			++winner_i;
		}
		while(loser_i<N)
		{
			int loser_id=loser_id_arr[loser_i];
			rank_id_arr[i]=loser_id;
			++i;
			++loser_i; 
		}
//		printf("rank: ");
//		for(int i=0;i<2*N;++i)
//			printf("%d, ",rank_id_arr[i]);
//		cout<<endl;
	}
	
	cout<<rank_id_arr[Q-1]+1<<endl;
	delete []winner_id_arr;
	delete []loser_id_arr;
	delete []score_arr;
	delete []competence_arr;
	delete []rank_id_arr;
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值