POJ - 2299 Ultra-QuickSort(树状数组)

来源:互联网 发布:无线信道测试软件 编辑:程序博客网 时间:2024/04/28 08:22

题目大意:给你N个数,每次只能交换相邻的两个数,问至少需要交换几次,才能使数变成升序

解题思路:需要交换的次数就是逆序对的个数,每交换一次,就相当于减少了一次逆序,而最后的升序,刚好逆序对是为0的,所以有多少的逆序对就要交换几次

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 500010;int n;int val[N], val2[N], bit[N];void init() {    for (int i = 1; i <= n; i++) {        scanf("%d", &val[i]);        val2[i] = val[i];    }    sort(val + 1, val + 1 + n);    memset(bit, 0, sizeof(bit));}int find(int num) {    int l = 1, r = n;    while (l <= r) {        int mid = (l + r) >> 1;        if (val[mid] == num) return mid;        else if (val[mid] > num) r = mid - 1;        else l = mid + 1;    }    return -1;}inline int lowbit(int x) {    return x & (-x);}int Query(int x) {    int ans = 0;    while (x) {        ans += bit[x];        x -= lowbit(x);    }    return ans;}void Modify(int x, int w) {    while (x < N) {        bit[x] += w;        x += lowbit(x);    }}void solve() {    long long ans = 0;    for (int i = 1; i <= n; i++) {        int pos = find(val2[i]);        Modify(pos, 1);        ans += i - Query(pos);    }    printf("%lld\n", ans);}int main() {    while (scanf("%d", &n) != EOF && n ) {        init();        solve();    }    return 0;}
0 0