CF1579E2 Array Optimization by Deque

CF1579E2

原题链接←Click it

题目大意:给定一个数组\(a\),依次将\(a\)中的每个元素放到一个双端队列中,求逆序对可能的最小值。

解题思路:首先对于\(a_1\),从前端插入和从尾端插入效果都是一样的。那么\(a_2\)无论是前端插入还是后端插入,都要考虑到\(a_1\),依次类推,对于任意\(a_i(i > 1)\),都必须考虑\(a_1,a_2,...,a_{i-1}\),那么就可以贪心地插入\(a_i\),如果在前端的逆序对数量少就插在前端,反之就差在尾端。因此就可以构建一颗平衡树,里面存放的是队列中已有元素的个数,每次可以用\(log\)的复杂度求出插入前端和插入尾端的逆序对个数。

参考代码:

struct BIT {
    int N;
    vector<int> c;
    BIT (int n) : N(n) {
        c.resize(n + 1, 0);
    }
    void add(int x, int d) {
        for(;x <= N; x += x & -x) {
            c[x] += d;
        }
    }
    int sum(int x) {
        int res = 0;
        for(;x; x -= x & -x) {
            res += c[x];
        }
        return res ;
    }
    int sum(int x, int y) {
        return sum(y) - sum(x);
    }
};
void solve() {
    int n;
    cin >> n;
    vector<int> a(n);
    for(int i = 0; i < n; i ++) {
        cin >> a[i];
    }
    vector<int> b = a;
    sort(b.begin(), b.end());
    b.resize(unique(b.begin(), b.end()) - b.begin());
    for(int i = 0; i < n; i ++) {
        a[i] = lower_bound(b.begin(), b.end(), a[i]) - b.begin() + 1;
    }
    int cnt = b.size();
    ll res = 0;
    BIT bit(cnt);
    for(int i = 0; i < n; i ++) {
        res += min(bit.sum(a[i] - 1), bit.sum(a[i], cnt));
        bit.add(a[i], 1);
    }
    cout << res << '\n';
}

posted @ 2022-03-26 01:07  Muly  阅读(261)  评论(0)    收藏  举报