洛谷P1966 火柴排队 题解 离散化+逆序对

题目链接:https://www.luogu.com.cn/problem/P1966

解题思路:

答案最小则,a的第i小元素和b的第i小元素配。

先将 a、b 离散化成 0~n-1。

然后假设b为有序的情况下a的每个元素是什么,推导出a。

然后对a求逆序对(我这里用归并排序做的)。

示例代码:

#include <bits/stdc++.h>
using namespace std;
const long long MOD = 100000000 - 3;
const int maxn = 100010;
int n, a[maxn], b[maxn], tmp[maxn], pa[maxn];
long long ans;
void merge_sort(int L, int R) {
    if (L == R) return;
    int mid = (L + R) / 2;
    int i = L, j = mid + 1, k = L;
    merge_sort(L, mid);
    merge_sort(mid+1, R);
    while (i <= mid && j <= R) {
        if (a[i] < a[j]) {
            b[k++] = a[i++];
        }
        else {
            ans += mid - i + 1;
            b[k++] = a[j++];
        }
    }
    while (i <= mid) {
        b[k++] = a[i++];
    }
    while (j <= R) {
        b[k++] = a[j++];
    }
    for (i = L; i <= R; i ++) a[i] = b[i];
}
int main() {
    cin >> n;
    for (int i = 0; i < n; i ++) {
        cin >> a[i];
        tmp[i] = a[i];
    }
    sort(tmp, tmp+n);
    for (int i = 0; i < n; i ++) a[i] = lower_bound(tmp, tmp+n, a[i]) - tmp;
    for (int i = 0; i < n; i ++) {
        cin >> b[i];
        tmp[i] = b[i];
    }
    sort(tmp, tmp+n);
    for (int i = 0; i < n; i ++) b[i] = lower_bound(tmp, tmp+n, b[i]) - tmp;
    for (int i = 0; i < n; i ++) pa[a[i]] = i;
    for (int i = 0; i < n; i ++) {
        int j = pa[b[i]];
        a[j] = i;
    }
    merge_sort(0, n-1);
    ans %= MOD;
    cout << ans << endl;
    return 0;
}
posted @ 2020-10-13 23:40  quanjun  阅读(97)  评论(0编辑  收藏  举报