这个题两个考点吧,一个逆序对,一个离散化。
一、离散化
1、归并排序
归并排序采用递归的方式,合并两个有序序列a[l~mid]与a[mid+1~r]可以采用两个指针i与j分别对二者进行扫描的方式,不断比较两个指针所指向的数值a[i]与a[j]的大小,将小的那个加入到排序的结果数组中。若小的那个是a[j],则a[i~mid]都要比a[j]大,他们都会与a[j]构成逆序对,可以顺便统计到答案中。
——lyd《算法竞赛进阶指南》
#include <bits/stdc++.h> using namespace std; const int MAXN = 5e5 + 5; int a[MAXN], r[MAXN], n; long long ans = 0; void msort(int s, int t) { if (s == t) { return; } int mid = (s + t) >> 1; msort(s, mid), msort(mid + 1, t); int i = s, j = mid + 1, k = s; while (i <= mid && j <= t) if (a[i] <= a[j]) r[k++] = a[i++]; else r[k++] = a[j++], ans += (long long)mid - i + 1; while (i <= mid) r[k] = a[i], k++, i++; while (j <= t) r[k] = a[j], k++, j++; for (int i = s; i <= t; ++i) a[i] = r[i]; } int main() { cin >> n; for(register int i = 1; i <= n; ++i) cin >> a[i]; msort(1,n); cout << ans << endl; }
二、map离散化
这个好东西我竟然现在才知道。。。利用map对数据进行编号,比如一个字符串就可以这样进行编号。。。
三、最后上代码
这个题利用map对字符串进行离散化,之后就是统计逆序对的板子。。。
(正解貌似是trie树)
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 5; map<string, int> m; int a[MAXN]; int r[MAXN]; int n; long long ans = 0; void msort(int s, int t) { if (s == t) { return; } int mid = (s + t) >> 1; msort(s, mid), msort(mid + 1, t); int i = s, j = mid + 1, k = s; while (i <= mid && j <= t) if (a[i] <= a[j]) r[k++] = a[i++]; else r[k++] = a[j++], ans += (long long)mid - i + 1; while (i <= mid) r[k] = a[i], k++, i++; while (j <= t) r[k] = a[j], k++, j++; for (int i = s; i <= t; ++i) a[i] = r[i]; } int main() { scanf("%d", &n); string s; for (register int i = 1; i <= n; ++i) { cin >> s; m[s] = i; } for (register int i = 1; i <= n; ++i) { cin >> s; a[i] = m[s]; } msort(1, n); cout << ans << endl; }