离散化及树状数组求逆序对

用树状数组求逆序对的时候注意:要统计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=1; i<=n; i++) {
        ans += i - 1 - getsum(b[i]);
        add(b[i], 1);
    }
    printf("%lld", ans);
    return 0;
} 
posted @ 2018-11-02 18:24  Zolrk  阅读(190)  评论(0编辑  收藏  举报