重庆NKOJ2180-交换排序

问题描述

题面

给出一个长度为n的整数数列,你每一次可以随意交换其中任意相邻两个数字的位置。问你至少交换几次,才能使得这个数列是个单调递增数列。
例如有数列:9 1 0 5 4
结果极限排序后:0 1 4 5 9

输入格式

有多组输入数据,对于每组输入数据:
第一行,一个整数 n(n < 500,000)表示待排序的数列长度。
接下来n行,第i行表示数列中的第i个整数a[i](0 ≤ a[i] ≤ 999,999,999)
当n=0时,表示输入结束。

输出格式

对于每组输入数据,输出一个整数,表示最少交换的次数

样例

样例输入

5
9
1
0
5
4
3
1
2
3
0

样例输出

6
0

提示

共两组输入数据,分别是:
5
9
1
0
5
4

3
1
2
3

注意,结果可能超过int的范围,建议用long long 类型
long long的定义方式为:long long x;
long long 的输出有两种方式:
c++方式:cout<<x;
c语言方式:printf(“%lld”,x);
scanf(“%lld”,&x);

思路

不得不说,这个输入放在整个OJ也是相当炸裂的存在
拿到题,大部分脑子正常的人都会想到冒泡。
有关排序的算法可以参考我的这篇文章。
冒泡部分代码:

long long int bubble_sort(long long int* arr,long long int len)
{
    bool ok = 0;
    long long int ans = 0;
    for(long long int i = 0; i < len-1; i++){
    	ok = 1;
        for(long long int j = 0; j < len-1-i; j++){
            if(arr[j] > arr[j+1]){
            	ok = 0;
            	ans++;
                swap(arr[j],arr[j+1]);
            }
        }
        if(ok){
    		break;
		}
    }
    return ans;
}

完整代码:

#include<bits/stdc++.h>
using namespace std;
long long int bubble_sort(long long int* arr,long long int len)
{
    bool ok = 0;
    long long int ans = 0;
    for(long long int i = 0; i < len-1; i++){
    	ok = 1;
        for(long long int j = 0; j < len-1-i; j++){
            if(arr[j] > arr[j+1]){
            	ok = 0;
            	ans++;
                swap(arr[j],arr[j+1]);
            }
        }
        if(ok){
    		break;
		}
    }
    return ans;
}
long long int a[500010];
int main ()
{
	long long int n;
	while(true){
		memset(a,0,sizeof(a));
		scanf("%lld",&n);
		if(n == 0){
			break;
		}
		for(long long int i = 0; i < n; i++){
			scanf("%lld",&a[i]);
		}
		printf("%lld\n",bubble_sort(a,n));
	}
	return 0;
}

没丽的TLE向你招手
没丽的TLE向你招手……

在马桶上磨叽了半个小时,发现冒泡排序行不通,只有用并归排序。
有关排序的算法可以参考我的这篇文章。

long long int ans = 0;
void merger(long long int* a,long long int* r,long long int L,long long int Mid,long long int R){
	long long int i,j,k;
	i = L;
	j = Mid + 1;
	k = L;
	while(i <= Mid && j <= R){
		if(a[i] <= a[j]){
			r[k] = a[i];
			k++;
			i++;
		}else{
			r[k] = a[j];
			k++;
			j++;
			ans += Mid-i+1;
		}
	}
	while(i <= Mid){
		r[k] = a[i];
		k++;
		i++;
	}
	while(j <= R){
		r[k] = a[j];
		k++;
		j++;
	}
	for(int m = L; m <= R; m++){
		a[m] = r[m];
	}
}
void merge_sort(long long int* a,long long int* r,long long int L,long long int R){
	if(L < R){
		long long int mid  = (L+R)/2;
		merge_sort(a,r,L,mid);
		merge_sort(a,r,mid+1,R);
		merger(a,r,L,mid,R);
	}
}

AC代码

老朋友了

#include<bits/stdc++.h>
using namespace std;
long long int ans = 0;
void merger(long long int* a,long long int* r,long long int L,long long int Mid,long long int R){
	long long int i,j,k;
	i = L;
	j = Mid + 1;
	k = L;
	while(i <= Mid && j <= R){
		if(a[i] <= a[j]){
			r[k] = a[i];
			k++;
			i++;
		}else{
			r[k] = a[j];
			k++;
			j++;
			ans += Mid-i+1;
		}
	}
	while(i <= Mid){
		r[k] = a[i];
		k++;
		i++;
	}
	while(j <= R){
		r[k] = a[j];
		k++;
		j++;
	}
	for(int m = L; m <= R; m++){
		a[m] = r[m];
	}
}
void merge_sort(long long int* a,long long int* r,long long int L,long long int R){
	if(L < R){
		long long int mid  = (L+R)/2;
		merge_sort(a,r,L,mid);
		merge_sort(a,r,mid+1,R);
		merger(a,r,L,mid,R);
	}
}
long long int a[500010],b[500010];
int main ()
{
	long long int n;
	while(true){
		scanf("%lld",&n);
		if(n == 0){ 
			break;
		}
		ans = 0;
		for(long long int i = 0; i < n; i++){
			scanf("%lld",&a[i]);
		}
		merge_sort(a,b,0,n-1);
		printf("%lld\n",ans);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值