HDU 1394 Minimum Inversion Number (线段树 or BIT)

题意: 给定一个序列, 可以不断的通过把第一个数移到最后一位, 生成新的序列, 求所有序列的最小逆序数

分析: 线段树单点更新, 区间查询啦~ 或者另一种想法也可以, 见注释吧

代码: 线段树

//
//  Created by TaoSama on 2015-09-18
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 5e3 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n, a[N];
int sum[N << 2];

#define root 0, n - 1, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1

void push_up(int rt) {
    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}

void update(int o, int l, int r, int rt) {
    if(l == r) {
        sum[rt]++;
        return;
    }
    int m = l + r >> 1;
    if(o <= m) update(o, lson);
    else update(o, rson);
    push_up(rt);
}

int query(int L, int R, int l, int r, int rt) {
    if(L <= l && r <= R) {
        return sum[rt];
    }
    int m = l + r >> 1, ret = 0;
    if(L <= m) ret += query(L, R, lson);
    if(R > m) ret += query(L, R, rson);
    return ret;
}

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(scanf("%d", &n) == 1) {
        int cur = 0;
        memset(sum, 0, sizeof sum);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", a + i);
            cur += query(a[i], n - 1, root);
            update(a[i], root);
        }

        int ans = cur;
        for(int i = 1; i < n; ++i) {
            int tmp = n - a[i] - 1 - a[i]; //big: n-a[i]-1,  small: a[i]
            cur += tmp;
            ans = min(ans, cur);
        }
        printf("%d\n", ans);
    }
    return 0;
}

BIT:

//
//  Created by TaoSama on 2015-09-18
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 5e3 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n, a[N];

int b[N];
void add(int i) {
    for(; i <= n; i += i & -i) ++b[i];
}

int sum(int i) {
    int ret = 0;
    for(; i; i -= i & -i) ret += b[i];
    return ret;
}

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(scanf("%d", &n) == 1) {
        int cur = 0;
        memset(b, 0, sizeof b);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", a + i); ++a[i]; //avoid 0
            //cur num's total pairs - illegal pairs
            cur += i - 1 - sum(a[i]);
            add(a[i]);
        }

        int ans = cur;
        for(int i = 1; i < n; ++i) {
            cur += n - a[i] - (a[i] - 1);
            ans = min(ans, cur);
        }
        printf("%d\n", ans);
    }
    return 0;
}


你可能感兴趣的:(线段树)