Inversion(HDU_4911) 归并排序+逆序数对

Inversion

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 3171    Accepted Submission(s): 1154


Problem Description
bobo has a sequence a 1,a 2,…,a n. He is allowed to swap two  adjacent numbers for no more than k times.

Find the minimum number of inversions after his swaps.

Note: The number of inversions is the number of pair (i,j) where 1≤ii>a j.
 

Input
The input consists of several tests. For each tests:

The first line contains 2 integers n,k (1≤n≤10 5,0≤k≤10 9). The second line contains n integers a 1,a 2,…,a n (0≤a i≤10 9).
 

Output
For each tests:

A single integer denotes the minimum number of inversions.
 

Sample Input
 
   
3 1 2 2 1 3 0 2 2 1
 

Sample Output
 
   
1 2
 
题目大意:给出一组数字序列,求在最多进行k次相邻数调换后,有多少逆序数对;

解题思路:用归并排序求出原序列的逆序数对cnt,再求max(cnt - k, 0 ),即为答案;

#include"iostream"
#include"cstdio"
#include"cstring"
using namespace std;

int a[100005];
int b[100005];	//辅助数组 
long long cnt;

void Merge(int a[],int p,int q,int r, int b[]){ 
	int s = p, t = q + 1, k = p;
	while(s <= q && t <= r){
		if(a[s] <= a[t]){
			b[k ++] = a[s ++];
		}else{
			b[k ++] = a[t ++];
			cnt += (q - s + 1); // 在原序列a[s...q] > a[t],故有逆序数对 (q-s+1) 个 
		}
	}
	if(s == q + 1)
		for(;t <= r;t ++) b[k ++] = a[t];
	else
		for(;s <= q;s ++) b[k ++] = a[s];
	for(int i = p;i < k;i ++)
		a[i] = b[i];
}

void BottomUpSort(int a[],int first,int last,int b[]){
	if(first < last){
		int mid = (first + last) / 2;
		BottomUpSort(a, first, mid, b);
		BottomUpSort(a, mid + 1, last, b);
		Merge(a, first, mid, last, b);
	}
}

int main(){
	int n, k;
	while(scanf("%d%d",&n,&k) != EOF){
		cnt = 0;
		for(int i = 1;i <= n;i ++)
			scanf("%d",&a[i]);
		BottomUpSort(a,1,n, b);
		cnt = (cnt - k) > 0 ? (cnt - k) : 0;
		//for(int i = 1;i <= n;i ++) printf("%d ",a[i]);
		printf("\n");
		printf("%I64d\n",cnt);
	}
	return 0;
}


你可能感兴趣的:(ACM)