1. 程式人生 > >離散化及樹狀陣列求逆序對

離散化及樹狀陣列求逆序對

用樹狀陣列求逆序對的時候注意:要統計b[i]-1的字首和,因為可能有相同值的元素
不去重離散化:

sort(a+1, a+n+1, cmp);
for(int i=1; i<=n; i++) {
    if(i == 1 || a[i].val != a[i-1].val) {
        tot++;
    }
    b[a[i].ord] = tot;
}

去重離散化,和不去重差不多,只不過是放到一個新數組裡面,並且維護去重後有多少個元素,然後對新陣列按輸入順序再排個序就可以了

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 500000 + 10;
long long n,tree[MAXN],ans,tot,b[MAXN];
struct node{
    long long ord,val;
}a[MAXN];
void add(long long p, long long x) {
    while(p <= n) {
        tree[p] += x;
        p += (p&-p);
    }
}
int getsum(long long p) {
    long long sum = 0;
    while(p) {
        sum += tree[p];
        p -= (p&-p);
    }
    return sum;
}
bool cmp(node x, node y) {
    return x.val < y.val;
}
int main() {
    scanf("%lld", &n);
    for(int i=1; i<=n; i++) {
        scanf("%lld", &a[i].val);
        a[i].ord = i;
    }
    sort(a+1, a+n+1, cmp);
    for(int i=1; i<=n; i++) {
        if(i == 1 || a[i].val != a[i-1].val) {
            tot++;
        }
        b[a[i].ord] = tot;
    }
    for(int i=n; i; i--) {
        ans += getsum(b[i]-1);
        add(b[i], 1);
    }
    printf("%lld", ans);
    return 0;
}