信息学奥赛一本通(C++版)第二部分 基础算法 第二章 数据排序

本文是《信息学奥赛一本通(C++版)》第二部分基础算法的章节,重点讲解数据排序。通过14个典型题目,涵盖车厢重组、逆序对计算、第k名成绩查询、奇数单增序列等多个场景,详细解析冒泡排序、归并排序、结构体排序等算法的应用,旨在帮助读者深入理解数据排序的实现与优化。

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

第二章 数据排序

T1310 : 车厢重组

时间限制: 1000 ms 内存限制: 65536 KB

【题目描述】

  在一个旧式的火车站旁边有一座桥,其桥面可以绕河中心的桥墩水平旋转。一个车站的职工发现桥的长度最多能容纳两节车厢,如果将桥旋转 180 180 180度,则可以把相邻两节车厢的位置交换,用这种方法可以重新排列车厢的顺序。于是他就负责用这座桥将进站的车厢按车厢号从小到大排列。他退休后,火车站决定将这一工作自动化,其中一项重要的工作是编一个程序,输入初始的车厢顺序,计算最少用多少步就能将车厢排序。

【输入】

  有两行数据,第一行是车厢总数 N ( N ≤ 10000 ) N(N≤10000) N(N10000),第二行是 N N N个不同的数表示初始的车厢顺序。

【输出】

  一个数据,是最少的旋转次数。

【输入样例】
4
4 3 2 1
【输出样例】
6
【答案&代码】

  显然,题意说明,我们只能将相邻的车厢位置交换,这显然是冒泡排序的实现过程,所以这道题目,应该用冒泡排序来解决,代码如下。

#include<stdio.h>
void swap(int *a,int *b){
   /*交换a,b的值*/
	int temp=*a;
	*a=*b;
	*b=temp;
	return;
}
int main(void){
   
	int n;
	scanf("%d",&n);
	int box[n];
	for(int i=0;i<n;i++)
		scanf("%d",&box[i]);
	int sum=0;
	for(int i=1;i<n;i++)
		for(int j=0;j<i;j++)
			if(box[i]<box[j]){
   
				swap(&box[i],&box[j]);
				sum+=1;/*每交换1次,交换次数加1*/
			}
	printf("%d",sum);
	return 0;
}

T1311 : 求逆序对

时间限制: 1000 ms 内存限制: 65536 KB

【题目描述】

  给定一个序列 a 1 , a 2 , . . . , a n a_{1},a_{2},...,a_{n} a1,a2,...,an如果存在 i &lt; j i&lt;j i<j并且 a i &gt; a j a_{i}&gt;a_{j} ai>aj,那么我们称之为逆序对,求逆序对的数目。

【输入】

  第一行为 n n n,表示序列长度,接下来的 n n n行,第 i + 1 i+1 i+1行表示序列中的第 i i i个数。

【输出】

  所有逆序对总数。

【输入样例】
4
3
2
3
2
【输出样例】
3
【提示】

   N ≤ 1 0 5 , A i ≤ 1 0 5 N≤10^5,A_{i}≤10^5 N105,Ai105

【答案&代码】

  通过理性分析,我们可以得出,用所有的排序算法都可以完成本题,只需要统计每一个数所构成的逆序对个数即可,但是因为冒泡排序、插入排序等排序算法时间复杂度为 O ( n 2 ) O(n^{2}) O(n2),快速排序不稳定,此题应选用归并排序,代码如下。

#include<stdio.h>
int n,a[100001],c[100001];
unsigned long long ans=0;
void m(int l,int r){
   
	int mid=(l+r)/2,i,j,tmp;
	if(l>=r)
		return;
	m(l,mid);
	m(mid+1,r);
	tmp=l;
	for(i=l,j=mid+1;i<=mid&&j<=r;)
		if(a[i]>a[j])
			c[tmp++]=a[j++],ans+=mid-i+1;
		else c[tmp++]=a[i++];
	if(i<=mid)
		for(;i<=mid;)
			c[tmp++]=a[i++];
	if(j<=r)
		for(;j<=r;)
			c[tmp++]=a[j++];
	for(i=l;i<=r;i++)
		a[i]=c[i];
}
int main(void){
   
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",a+i);
	m(1,n);
	printf("lld",ans);
	return 0;
}

T1176 : 谁考了第k名

时间限制: 1000 ms 内存限制: 65536 KB

【题目描述】

  在一次考试中,每个学生的成绩都不相同,现知道了每个学生的学号和成绩,求考第 k k k名学生的学号和成绩。

【输入】

  第一行有两个整数,分别是学生的人数 n ( 1 ≤ n ≤ 100 ) n(1≤n≤100) n(1n100),和求第 k k k名学生的 k ( 1 ≤ k ≤ n ) k(1≤k≤n) k(1k

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值