首页 > 代码库 > POJ 2299 Ultra-QuickSort(树状数组+离散化)

POJ 2299 Ultra-QuickSort(树状数组+离散化)

http://poj.org/problem?id=2299

题意:
给出一组数,求逆序对。

 

思路:

这道题可以用树状数组解决,但是在此之前,需要对数据进行一下预处理。

这道题目的数据可以大到999,999,999,但数组肯定是无法开这么大的,但是每组数据最多只有500000个,那么,怎么办呢,离散化!

离散化,也就是将数据和1~n做一一映射。

比如:

9 1 0 5 4

离散化之后变成

5 2 1 4 3

这样的话,就可以放心的开数组啦!

至于树状数组的计算过程,我懒得写了,直接摘抄一下大神的http://www.cnblogs.com/shenshuyang/archive/2012/07/14/2591859.html

在离散结果中间结果的基础上,那么其计算逆序数的过程是这么一个过程。1,输入5,   调用upDate(5, 1),把第5位设置为11 2 3 4 50 0 0 0 1计算1-5上比5小的数字存在么? 这里用到了树状数组的getSum(5) = 1操作,现在用输入的下标1 - getSum(5) = 0 就可以得到对于5的逆序数为0。2. 输入2, 调用upDate(2, 1),把第2位设置为11 2 3 4 50 1 0 0 1计算1-2上比2小的数字存在么? 这里用到了树状数组的getSum(2) = 1操作,现在用输入的下标2 - getSum(2) = 1 就可以得到对于2的逆序数为1。3. 输入1, 调用upDate(1, 1),把第1位设置为11 2 3 4 51 1 0 0 1计算1-1上比1小的数字存在么? 这里用到了树状数组的getSum(1) = 1操作,现在用输入的下标 3 - getSum(1) = 2 就可以得到对于1的逆序数为2。4. 输入4, 调用upDate(4, 1),把第5位设置为11 2 3 4 51 1 0 1 1计算1-4上比4小的数字存在么? 这里用到了树状数组的getSum(4) = 3操作,现在用输入的下标4 - getSum(4) = 1 就可以得到对于4的逆序数为1。5. 输入3, 调用upDate(3, 1),把第3位设置为11 2 3 4 51 1 1 1 1计算1-3上比3小的数字存在么? 这里用到了树状数组的getSum(3) = 3操作,现在用输入的下标5 - getSum(3) = 2 就可以得到对于3的逆序数为2。6. 0+1+2+1+2 = 6 这就是最后的逆序数
 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<queue> 7 #include<cmath> 8 #include<map> 9 #include<stack>10 using namespace std;11 12 const int maxn=500000+5;13 14 int n;15 16 struct node17 {18     int val;19     int pos;20 }a[maxn];21 22 int b[maxn];23 int c[maxn];24 25 bool cmp(node a,node b)26 {27     return a.val<b.val;28 }29 30 int lowbit(int x)31 {32     return x&-x;33 }34 35 int sum(int x)36 {37     int ret=0;38     while(x>0)39     {40         ret+=c[x];41         x-=lowbit(x);42     }43     return ret;44 }45 46 void add(int x,int d)47 {48     while(x<=n)49     {50         c[x]+=d;51         x+=lowbit(x);52     }53 }54 55 int main()56 {57     //freopen("D:\\input.txt","r",stdin);58     while(~scanf("%d",&n) && n)59     {60         for(int i=1;i<=n;i++)61         {62             scanf("%d",&a[i].val);63             a[i].pos=i;64         }65         sort(a+1,a+1+n,cmp);66         for(int i=1;i<=n;i++)67             b[a[i].pos]=i;68         memset(c,0,sizeof(c));69         long long ans=0;70         for(int i=1;i<=n;i++)71         {72             add(b[i],1);73             ans+=i-sum(b[i]);74         }75         printf("%lld\n",ans);76     }77     return 0;78 }

 

POJ 2299 Ultra-QuickSort(树状数组+离散化)