GYM 102082 G What Goes Up Must Come Down【树状数组】

https://codeforces.com/gym/102082

题意:给你一个序列,你每次操作可以交换两个相邻的数,问你最少多少次操作可以让这个序列变成一个单峰序列。

分析:对于一个序列,按照顺序标记为1-N,每次交换相邻的两个数,那么交换后的序列的逆序数对数量就是操作的最小值。

而此时我们是需要一个单峰的排列,那么最大的数一定在中间,次大的数一定是往两边放,那么此时就有两种情况,但是无论怎么放,对下一个要放进来的数的编号的逆序数是不影响的,因为不会插入到中间,只会放到到两边,即当前已经放好的编号中,大于或小于某一个数的数的数量是确定的。然后逆序数用树状数组维护即可。注意当有很多值相等的元素时需要将其一起放进去,即保证相等的数相互之间不交换

#include "bits/stdc++.h"

namespace fastIO {
#define BUF_SIZE 100000
    bool IOerror = 0;

    inline char nc() {
        static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
        if (p1 == pend) {
            p1 = buf;
            pend = buf + fread(buf, 1, BUF_SIZE, stdin);
            if (pend == p1) {
                IOerror = 1;
                return -1;
            }
        }
        return *p1++;
    }

    inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }

    inline void read(int &x) {
        char ch;
        while (blank(ch = nc()));
        if (IOerror) return;
        for (x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
    }

#undef BUF_SIZE
};
using namespace fastIO;
using namespace std;

const int mod = 1e9 + 7;
int c[100004];

struct node {
    int w, id;

    bool friend operator<(node a, node b) {
        return a.w > b.w;
    }
} a[100004];

int lowbit(int x) {
    return x & (-x);
}

void updata(int x, int d) {
    while (x < 100004) {
        c[x] += d;
        x += lowbit(x);
    }
}

int que(int x) {
    int res = 0;
    while (x > 0) {
        res += c[x];
        x -= lowbit(x);
    }
    return res;
}


int main() {
    int n;
    read(n);
    memset(c, 0, sizeof(c));
    for (int i = 1; i <= n; ++i) {
        read(a[i].w);
        a[i].id = i;
    }
    sort(a + 1, a + 1 + n);
    long long ans = 0;
    for (int i = 1; i <= n; ++i) {
        int las = i;
        while (a[las + 1].w == a[i].w)las++;
        for (int j = i; j <= las; ++j) {
            ans += min(que(a[j].id), i - 1 - que(a[j].id));
        }
        for (int j = i; j <= las; ++j) {
            updata(a[j].id, 1);
        }
        i = las;
    }
    printf("%lld\n", ans);
}

猜你喜欢

转载自blog.csdn.net/qq_42671946/article/details/89843146