2014多校第五场1001 || HDU 4911 Inversion (归并求逆序数)

题目链接

题意 : 给你一个数列,可以随意交换两相邻元素,交换次数不超过k次,让你找出i < j 且ai > aj的(i,j)的对数最小是多少对。

思路 : 一开始想的很多,各种都想了,后来终于想出来这根本就是求逆序数嘛,可以用归并排序,也可以用树状数组,不过我们用树状数组做错了,也不知道为什么。求出逆序数来再减掉k次,就可以求出最终结果来了。求逆序数链接1链接2

 1 #include <stdio.h>
 2 
 3 int left[250003], right[250003];
 4 long long count;
 5 
 6 void merge(int* a, int p, int q, int r)
 7 {
 8     int i, j, k, n1, n2;
 9 
10     n1 = q-p+1;
11     n2 = r-q;
12     for (i=0; i<n1; i++)
13     {
14         left[i] = a[p+i];
15     }
16     for (i=0; i<n2; i++)
17     {
18         right[i] = a[q+i+1];
19     }
20     left[n1] = right[n2] = 0x7fffffff;
21 
22     i = j = 0;
23     for (k=p; k<=r; k++)
24     {
25         if (left[i] <= right[j])
26         {
27             a[k] = left[i];
28             i++;
29         }
30         else
31         {
32             a[k] = right[j];
33             j++;
34             count += n1-i;
35         }
36     }
37     return;
38 }
39 
40 void mergesort(int* a, int p, int r)
41 {
42     int q;
43     if (p < r)
44     {
45         q = (p+r)/2;
46         mergesort(a, p, q);
47         mergesort(a, q+1, r);
48         merge(a, p, q, r);
49     }
50     return ;
51 }
52 
53 int main()
54 {
55     int n, i, a[500001];
56     long long k;
57 
58     while (scanf("%d%I64d", &n,&k)!=EOF)
59     {
60         count = 0;
61         for (i=0; i<n; i++)
62         {
63             scanf("%d", &a[i]);
64         }
65         mergesort(a, 0, n-1);
66         count -=k;
67         if(count<0)count=0;
68         printf("%I64d
",count );
69     }
70 }
View Code
原文地址:https://www.cnblogs.com/luyingfeng/p/3893026.html