第二章 数据排序
T1310 : 车厢重组
时间限制: 1000 ms 内存限制: 65536 KB
【题目描述】
在一个旧式的火车站旁边有一座桥,其桥面可以绕河中心的桥墩水平旋转。一个车站的职工发现桥的长度最多能容纳两节车厢,如果将桥旋转 180 180 180度,则可以把相邻两节车厢的位置交换,用这种方法可以重新排列车厢的顺序。于是他就负责用这座桥将进站的车厢按车厢号从小到大排列。他退休后,火车站决定将这一工作自动化,其中一项重要的工作是编一个程序,输入初始的车厢顺序,计算最少用多少步就能将车厢排序。
【输入】
有两行数据,第一行是车厢总数 N ( N ≤ 10000 ) N(N≤10000) N(N≤10000),第二行是 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 < j i<j i<j并且 a i > a j a_{i}>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 N≤105,Ai≤105。
【答案&代码】
通过理性分析,我们可以得出,用所有的排序算法都可以完成本题,只需要统计每一个数所构成的逆序对个数即可,但是因为冒泡排序、插入排序等排序算法时间复杂度为 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(1≤n≤100),和求第 k k k名学生的 k ( 1 ≤ k ≤ n ) k(1≤k≤n) k(1≤k