火柴排队逆序对

Posted yuanweidao

tags:

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

题目链接:https://ac.nowcoder.com/acm/contest/2652/L

题目大意:

给两个长度均为 n 的数组,两个数组均为1~n全排列的一种。每次可交换任意一个数组中任意相邻的两个数,求最少多少次交换次数使得两个数组的距离最小。

距离的定义:若两个数组分别为a[],b[]。则他们的距离为 ∑(a[i] - b[i])²。

题解思路:

1.对两个数组进行排序,即得到两个数组的最小距离。(证明起来很麻烦,但我们都能感觉到这样就是最小距离)。

2.我们想要得到排序后的排列方式,那么就通过排序后对应位置上的数来记录排序前的对应位置。例如排列后,在下标为2的位置上的数依次为 4, 8。那么我们要记录4在排序前处于a数组中的哪个位置,8在排序前处于b数组中的哪个位置。将他们联系起来,作为我们排序后所要达到的目的。对于n个对应数字都如此记录下来,那么对得到的对应数组,计算我们需要交换多少次逆序对使得该数组变成有序,即为答案。

代码如下:

技术图片
 1 #include<stdio.h>
 2 #include<algorithm>
 3 using namespace std;
 4 typedef long long ll;
 5 const int MAXN = 1e6 + 100;
 6 const int mod = 99999997;
 7 
 8 int n;
 9 ll ans;
10 int pos[MAXN], temp[MAXN];
11 
12 struct Node
13 {
14     int val, id;
15 }a[MAXN], b[MAXN];
16 
17 bool cmp(Node a, Node b)
18 {
19     return a.val < b.val; 
20 }
21 
22 void merge(int l, int mid, int r)
23 {
24     int i = l, j = mid + 1, k = 0;
25     while(i <= mid && j <= r)
26     {
27         if(pos[i] < pos[j])
28             temp[++ k] = pos[i ++];
29         else
30         {
31             temp[++ k] = pos[j ++];
32             ans += (mid - i + 1) % mod;
33             ans %= mod;
34         }
35     }
36     while(j <= r)
37         temp[++ k] = pos[j ++];
38     while(i <= mid)
39         temp[++ k] = pos[i ++];
40     k = 0;
41     for(i = l; i <= r; i ++)
42         pos[i] = temp[++ k];
43 }
44 
45 void mergesort(int l, int r)
46 {
47     if(l < r)
48     {
49         int mid = (l + r) / 2;
50         mergesort(l, mid);
51         mergesort(mid + 1, r);
52         merge(l, mid, r);
53     }
54 }
55 
56 int main()
57 {
58     scanf("%d", &n);
59     for(int i = 1; i <= n; i ++)
60     {
61         scanf("%d", &a[i].val);
62         a[i].id = i;
63     }
64     for(int i = 1; i <= n; i ++)
65     {
66         scanf("%d", &b[i].val);
67         b[i].id = i;
68     }    
69     sort(a + 1, a + 1 + n, cmp);
70     sort(b + 1, b + 1 + n, cmp);
71     for(int i = 1; i <= n; i ++)
72         pos[a[i].id] = b[i].id;
73     mergesort(1, n);
74     printf("%lld
", ans);
75     return 0;
76 }
View Code

 

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

Codevs 3286 火柴排队 2013年NOIP全国联赛提高组 树状数组,逆序对

P1966 火柴排队——逆序对(归并,树状数组)

火柴排队逆序对

luogu 1966 火柴排队 离散化+逆序对

LG-P2804 神秘数字/LG-P1196 火柴排队 归并排序, 逆序对

P1966 火柴排队