HDU 4944 逆序数对

Posted 树的种子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 4944 逆序数对相关的知识,希望对你有一定的参考价值。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911

题意:

给出一个序列,可以相邻的交换k次,求 k 次之后,逆序数对最少是多少;

 

分析:

可以发现,无论怎么交换之后,总共的逆序数对只会-1,那么结果就是,将这个序列排整齐时,要两两交换的次数-k;题目就转换为求这个序列的逆序数对有多少;

这样的两两交换好像是冒泡排序,冒泡排序是O(n^2);

正确解法是归并排序;当我们合并两个有序序列时,如果,要将后面的插入到前一个中间,那么这里就有m-i+1个逆序数对;

技术分享
 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int maxn = 1e5 + 5;
 6 
 7 __int64 cnt,k;
 8 int a[maxn],c[maxn];
 9 
10 
11 void merge(int* a,int first,int mid,int last,int* c) {
12     int i = first,j=mid+1;
13     int m = mid,n=last;
14     int k = 0;
15     while(i<=m||j<=n) {
16         if(j>n||(i<=m&&a[i]<=a[j])) {
17             c[k++] = a[i++];
18         }
19         else {
20             c[k++] = a[j++];
21             cnt += (m-i+1);
22         }
23     }
24     for(i=0;i<k;i++)
25         a[first+i] = c[i];
26 }
27 
28 void mergeSort(int* a,int first,int last,int* c) {
29     if(first<last) {
30         int mid = (first+last)/2;
31         mergeSort(a,first,mid,c);
32         mergeSort(a,mid+1,last,c);
33         merge(a,first,mid,last,c);
34     }
35 }
36 
37 int main()
38 {
39     int n;
40     while(~scanf("%d%I64d",&n,&k)) {
41         for(int i=0;i<n;i++)
42             scanf("%d",&a[i]);
43         memset(c,0,sizeof(c));
44         cnt = 0;
45         mergeSort(a,0,n-1,c);
46         printf("%lld\n",max(cnt-k,0LL));
47     }
48     return 0;
49 }
View Code

 

以上是关于HDU 4944 逆序数对的主要内容,如果未能解决你的问题,请参考以下文章

HDU 4911 Inversion 树状数组求逆序数对

hdu_4944_FSF’s game

白话经典算法系列之九 从归并排序到数列的逆序数对(微软笔试题)

怎样求数组中逆序数对的个数(java)

CodeForces911D 逆序对

LeetCode 315. Count of Smaller Numbers After Self (逆序数对)