树状数组_poj_2299_Ultra-QuickSort

来源:互联网 发布:振华重工 知乎 编辑:程序博客网 时间:2024/06/06 05:18

题目链接

题意:求逆序对。
方法:树状数组+离散化

这道题数据量比较大,直接开数组是不行的,所以采取离散化的办法,其实也就是弄一个映射关系而已。

具体思想就是排好序,建立映射关系,然后开一个一样大的数组,按照原来的输入顺序在其映射的位置加1 (加的时候用树状数组的更新函数),然后用区间查询函数统计它前面有多少个数已经输入了(即区间求和),在这个数前面的都是比它小的数,所以算一下就知道有多少比它大的数在它前面了,即逆序对求出。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm> using namespace std;const int maxn=500000+50;int a[maxn],ref[maxn];int N;struct node{int v,pos;}nod[maxn];bool cmp(node x,node y){    return x.v<y.v;}void Add(int k){    while(k<=N){        a[k]+=1;        k+=k&-k;    }}int query(int x){    int ans=0;    while(x){        ans+=a[x];        x-=x&-x;    }    return ans;}int main(){    while(cin>>N&&N){        for(int i=1;i<=N;i++){            scanf("%d",&nod[i].v);            nod[i].pos=i;        }        memset(a,0,sizeof(a));        sort(nod+1,nod+1+N,cmp);        for(int i=1;i<=N;i++)ref[nod[i].pos]=i;        long long ans=0;        for(int i=1;i<=N;i++){            Add(ref[i]);            ans+=i-query(ref[i]);        }        cout<<ans<<endl;    }    return 0;}
0 0