POJ 2299 (树状数组)

来源:互联网 发布:化学实验软件中文版 编辑:程序博客网 时间:2024/05/22 05:23

题意:

给出n个数字,求出逆序数。

思路:

树状数组能很容易的求出逆序数,不过前提是以数列本身当作数组C的下标。因为以数
组本身当作下标的时候每一次进行update和sum的时候都能找到前边比x小的数的个
数,这道题由于数组上界太大,无法开那么大的数组所以需要离散化,将原本的数字
排序后放入reflect中,其每一个数字的原来的位置不变,这样就能以位子作为数组下
进行计算。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 500005;struct Node{    int val;    int pos;}node[MAXN];int n,c[MAXN],reflect[MAXN];int cmp(Node a,Node b){    return a.val < b.val;}int lowbit(int x){    return x&-x;}int update(int x){    while(x <= n) {        c[x] += 1;        x += lowbit(x);    }}int sum(int x){    int sum = 0;    while(x > 0) {        sum += c[x];        x -= lowbit(x);    }    return sum;}int main(){    //freopen("in.txt","r",stdin);    while(scanf("%d",&n) != EOF && n) {        memset(c,0,sizeof(c));        for(int i = 1;i <= n; i++) {            scanf("%d",&node[i].val);            node[i].pos = i;        }        sort(node+1,node+n+1,cmp);        for(int i = 1;i <= n; i++)            reflect[node[i].pos] = i;        long long ans = 0;        for(int i = 1;i <= n; i++) {            update(reflect[i]);            ans += i-sum(reflect[i]);        }        printf("%lld\n",ans);    }    return 0;}
0 0