C++ 分治算法-归并排序与逆序对

来源:互联网 发布:vscode 调试网页 编辑:程序博客网 时间:2024/05/30 05:42

归并排序

分治过程:

1 分成两半

2 分别进行归并排序(递归进行)

3 合并成一个有序表(归并思想)

#include <iostream>using namespace std;int cnt;void merge(int *a, int l, int r, int *tmp) { //a数组在区间[l, r)内排序 if(r - l < 2) return; //如果只有两个元素 return; int mid = l + ((r - l)/2);int pos1 = l, pos2 = mid, pos_tmp = l;merge(a, l, mid, tmp); //排序好左边 merge(a, mid, r, tmp); //排序好右边 while(pos1 < mid || pos2 < r) { //合并两个有序序列 if(pos2 >= r || (pos1 < mid && a[pos1] <= a[pos2])) tmp[pos_tmp++] = a[pos1++];else tmp[pos_tmp++] = a[pos2++];}for(int i=l; i<r; i++) a[i] = tmp[i];}int a[100001], tmp[100001], n;int main() {cin >> n;for(int i=1; i<=n; i++) cin >> a[i];merge(a, 1, n+1, tmp);cout << cnt << endl;return 0;}



逆序对问题

 

题目描述

猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。

输入输出格式

输入格式:

第一行,一个数n,表示序列中有n个数。

第二行n个数,表示给定的序列。

输出格式:

给定序列中逆序对的数目。

输入输出样例

输入样例: 
65 4 2 6 3 1
输出样例: 
11




说明

对于50%的数据,n≤2500

对于100%的数据,n≤40000。

 

在归并的基础上稍作改动

 

在两个序列归并时,当右边的序列中的一个元素进入了tmp

说明它比左边序列中还没进入tmp每一个都小

满足了a[i] < a[j].

因为右边序列元素的下标大于左边序列元素的下标,因此满足i > j.

 【只要加上一条语句】
while(pos1 < mid || pos2 < r) {if(pos2 >= r || (pos1 < mid && a[pos1] <= a[pos2])) tmp[pos_tmp++] = a[pos1++];else {tmp[pos_tmp++] = a[pos2++];cnt += mid - pos1; //此时左边一半的元素个数}}


#END_BLOG
原创粉丝点击