首页 > 其他分享 >瑞士轮——结构体&&(快速排序 or 归并排序?)

瑞士轮——结构体&&(快速排序 or 归并排序?)

时间:2024-04-27 22:55:30浏览次数:19  
标签:归并 include grade int && 排序 id define

题目链接:https://www.luogu.com.cn/problem/P1309

题意应该非常明确了(这里就不细讲了):有2*N个人,首先根据成绩进行排序,相邻的两个人进行比赛,强的人成绩+1,输的人成绩不变,最后又根据成绩进行排序,进行r次操作,如果成绩相同,初始时序号在前的排前面,最后输出第q个人的序号。

思路:

  1. 快速排序和结构体,首先用结构体存数据,然后用STL库里面的sort函数,每次比较完更新就排一次序(具体实现看下列代码)。这样你会发现时间会爆炸,也就是TLE,那么为什么会出现这种情况呢?

  2. 那就了解一下sort函数
    sort本质就是杂乱的二分(胡乱找中间点),左右两边俩俩交换,时间复杂度非常不稳定
    稳定的时候时间复杂度O(nlogn)左右,最坏的情况时间复杂度能到n的平方左右,这题你就能发现俩俩比较后不一定要交换,而快速排序是每次都交换,所以多了很多无用的操作,此题就卡了数据

  3. 时间复杂度低的排序方法除了快速排序就是归并排序,归并排序时间复杂度稳定在O(nlogn),这题两两比较,赢得进A数组,输的进B数组,最后对A和B进行合并。
    为啥可以直接合并?初始状态已近是排好序,有序状态,相邻俩俩比较,A,B序列依旧都是有序的,所以可以直接合并,时间复杂度(n)
    例如:

如果对归并排序不熟悉的请移步这篇博客https://www.cnblogs.com/expect-999/p/17599008.html

快速排序sort(正确80%)

#define _CRT_SECURE_NO_WARNINGS 1

#define all(C) C.begin(),C.end()
#define S second
#define F first
#define PB push_back
#define mod 1000000007
#define import ios_base::sync_with_stdio(false);cin.tie(NULL)

#include <cstring>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <map>

using namespace std;
typedef long long ll;
const int N = 1e6 + 10;

int n,x,k;

struct stu
{
	int id;
	int grade;
	int ability;
}q[N];

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

signed main()
{

	cin >> n >> x >> k;

	for (int i = 1; i <=2*n; ++i)
	{
		q[i].id = i;
		cin >> q[i].grade;
	}

	for (int i = 1; i <= 2 * n; ++i) cin >> q[i].ability;

	sort(q+1, q + 2*n+1,cmp);

	while (x--)
	{
		for (int i = 1; i <= 2 * n; i+=2)
		{
			if (q[i].ability > q[i + 1].ability) q[i].grade++;
			else q[i + 1].grade++;
		}
		sort(q + 1, q + 2 * n + 1,cmp);
	}

	printf("%d", q[k].id);

	return 0;
}

归并排序(100%)

#define _CRT_SECURE_NO_WARNINGS 1

#define all(C) C.begin(),C.end()
#define S second
#define F first
#define PB push_back
#define mod 1000000007
#define import ios_base::sync_with_stdio(false);cin.tie(NULL)

#include <cstring>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <map>

using namespace std;

const int N = 2e5 + 10;

struct stu
{
	int id; //序号
	int grade; //成绩
}q[N],A[N],B[N];

int n, r, t;
int w[N]; // 能力

bool cmp(stu a, stu b)
{   //如果成绩不相等,成绩高的排前面,相等情况下序号小的排前面
	if (a.grade != b.grade) return a.grade > b.grade; 
	else return a.id < b.id;
}

void merge_sort()
{
	int i = 1, j = 1, k = 1;
	while (i <= n && j <= n) // A,B中数量都是n
	{
		if (A[i].grade > B[j].grade || (A[i].grade == B[j].grade && A[i].id < B[j].id) )
		{
			q[k].grade=A[i].grade;
			q[k++].id=A[i++].id;
		}
		else
		{
			q[k].grade = B[j].grade;
			q[k++].id = B[j++].id;
		}
	}

	while (i <= n) {
		q[k].grade = A[i].grade;
		q[k++].id = A[i++].id;
	}

	while(j<=n)
	{
		q[k].grade = B[j].grade;
		q[k++].id = B[j++].id;
	}
}


signed main()
{
	cin >> n >> r >> t ;
    //输入相应的数据
	for (int i = 1; i <= n * 2; ++i)
	{
		cin >> q[i].grade;
		q[i].id = i;
	}

	for (int i = 1; i <= n * 2; ++i) cin >> w[i];

	sort(q + 1, q + 2 * n + 1, cmp);

	while (r--)
	{
		int tt = 1; 
		for (int i = 1; i <= 2 * n; i += 2)
		{
			if (w[q[i].id] > w[q[i + 1].id])
			{
				A[tt].grade = q[i].grade + 1; 
				A[tt].id = q[i].id;
				B[tt].grade = q[i + 1].grade;
				B[tt].id = q[i + 1].id;
				tt++;
             //俩俩比较,进行成绩更新,分别进去A,B两个数组,胜者入A,败者入B
			}
			else
			{
				A[tt].grade = q[i+1].grade + 1;
				A[tt].id = q[i+1].id;
				B[tt].grade = q[i].grade;
				B[tt].id = q[i].id;
				tt++;
			}
		}
		merge_sort(); //归并排序
	}

	cout << q[t].id << endl;

	return 0;
}

本人蒟蒻,如有错误或不恰当的地方还望指点,如果对您有帮助,希望给个免费的点赞和关注,这对我很重要,感谢观看我的博客

标签:归并,include,grade,int,&&,排序,id,define
From: https://www.cnblogs.com/expect-999/p/18162711

相关文章

  • 基数排序 LSD py
    链接:https://www.nowcoder.com/questionTerminal/1e68ccb2cbc74c3d9e0dea0c568789b8设数组S[]={154,265,146,31,213,14,157,189,91,10,111,123},采用最低位优先(LSD)基数排序将S排列成升序序列,第1趟分配收集后元素14之前,之后紧邻的元素是()第1趟分配收集后的结果为:10,31,91,111,213,......
  • 排序算法
    1.直接插入排序:直接插入排序就是把待排序的元素逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。实际中我们玩扑克牌时,就用了插入排序的思想voidInsertSort(int*arr,intsize)//直接插入排序{for(inti=0;i<size-1;i+......
  • 实验三 数据排序
    一、实验题目:软件测试二、实验目的1、熟悉开发环境下的自动化测试工具;1、利用自动化测试工具进行自动化单元测试。三、实验内容1、选择开发环境,IDEA或PYCHARM任选其一;2、基于所选择的开发环境实现对输入的n个整数进行排序的代码;3、对所编写代码设计测试用例;4、基于所选择......
  • 选择排序测试
    一、实验题目:软件测试二、实验目的1、熟悉开发环境下的自动化测试工具;1、利用自动化测试工具进行自动化单元测试。三、实验内容1、选择开发环境,IDEA或PYCHARM任选其一;2、基于所选择的开发环境实现对输入的n个整数进行排序的代码;3、对所编写代码设计测试用例;4、基于所选择......
  • Elasticsearch - Text字段排序
    插入数据DELETE/websitePUT/website{"mappings":{"properties":{"title":{"type":"text"}}}}PUT/website/_doc/1{"title":"firstclass"}PU......
  • 排序6-归并排序
    排序6-归并排序归并排序思路每次将序列分为二组,如果这两组数据是有序的,在辅助空间进行排序.细分至只有一个数据时序列是有序的,从此开始向上合并临近小组分组合并//分组合并,将要合并的两个序列按大小填入辅助空间中voidMerge(intarr[],intstart,intend,i......
  • DRF之过滤 排序 分页
    DRF之过滤排序分页使用【过滤排序分页】都需要在继承了GenericAPIView的视图类下使用并指定类属性【queryset和serializer_class】【一】过滤#所有过滤类都继承【BaseFilterBackend】fromrest_framework.filtersimportBaseFilterBackend【1】drf自带的过滤#......
  • 笔记:拓扑排序
    定义拓扑排序(Topologicalsorting),是对一个DAG排序的算法。对于排序后的序列\(s\),设\(t_i\)是节点\(i\)在\(s\)中的位置,那么该DAG上的每条边\(u\tov\),\(t_u<t_v\)。换句话说,就是每条边\(u\tov\),\(u\)不能在\(v\)的后面。模板link。考虑两种算法,分别基于广......
  • 二分法,冒泡排序
    Ⅰ算法之二分法算法其实就是解决问题的有效方法'''二分法使用有前提:数据集必须有先后顺序(升序,降序)''''''二分法原理 获取数据集中间的元素比对大小 如果中间元素大于目标数据那么保留数据集的左边一半 如果中间元素小于目标数据那么保留数据集的右边一半 针对剩......
  • 冒泡排序
    packageArray;importjava.util.Arrays;//冒泡排序//1.比较数组中,两个相邻的元素,如果第一个数比第二个数大,我们就交换他们的位置//2.每一次比较,都会产生一个最大,或者最小的数字//3.下一轮测试可以少一次排序//4.依次循环,直到结束publicclassDemo06{publicstaticvoid......