2021牛客多校4_Inverse Pair

Inverse Pair

题目传送门:

题目传送门

题面:

2021牛客多校4_Inverse Pair

题目大意:

给定一个无重复的排列,每个元素可以执行+1的操作或不变,求操作后最少的逆序对对数。

思路:

思考怎么加可以减少逆序对对数,如果x 在 x+1 的后面, 则可以通过操作让逆序对减少。
而且因为是排列,所以不会增加逆序对(+1也最多变得和某个数一样,不会再变大了)。
但是可能后续操作会覆盖之前消除的记录。
2021牛客多校4_Inverse Pair
如题解。
但实际上也没那么复杂,遇到如果x 在 x+1 的后面,直接全部暴力让x+1,最后再跑一遍看有几个逆序对。

merge_sort求逆序数对的方法《挑程》上有。

代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 2e5 + 7;
int q[maxn], tmp[maxn];
int vis[maxn] = {0};

//ll merge_sort(int l, int r) {
//    if (l >= r) return 0;
//    //区间没有元素返回
//    int mid = l + r >> 1;
//    ll ans = merge_sort(l, mid) + merge_sort(mid + 1, r);
//    int cnt = 0;
//    int i = l;
//    int j = mid + 1;
//    while (j <= r && i <= mid) {
//        if (q[i] <= q[j])
//            tmp[cnt++] = q[i++];
//        else {
//            ans += mid - i + 1;
//            tmp[cnt++] = q[j++];
//        }
//    }
//    while (j <= r) tmp[cnt++] = q[j++];
//    while (i <= mid) tmp[cnt++] = q[i++];
//    for (int i = l, j = 0; i <= r; i++, j++) q[i] = tmp[j];
//    return ans;
//}
ll merge_sort(int l, int r) {
    if (l >= r)
        return 0;
    int mid = l + r >> 1;
    ll ans = merge_sort(l, mid) + merge_sort(mid + 1, r);
    int i = l, j = mid + 1, k = 0;
    while (i <= mid && j <= r)
        if (q[i] <= q[j])
            tmp[k++] = q[i++];
        else
            tmp[k++] = q[j++], ans += (ll) mid - i + 1;
    while (i <= mid)
        tmp[k] = q[i], k++, i++;
    while (j <= r)
        tmp[k] = q[j], k++, j++;
    for (int i = l, j = 0; i <= r; j++, i++)
        q[i] = tmp[j];
    return ans;
}

int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> q[i];
    for (int i = 1; i <= n; i++) {
        if (vis[q[i] + 1])q[i]++;
        else vis[q[i]] = 1;
    }
    cout << merge_sort(1, n) << endl;
    return 0;
}



上一篇:Gym 102346A. Artwork (并查集)


下一篇:element 动态合并表格---进阶版