码迷,mamicode.com
首页 > 编程语言 > 详细

poj 2299 Ultra-QuickSort(归并排序或是bit 树+离散化皆可)

时间:2015-08-26 21:57:03      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:

题意:给一个数组,计算需要的冒泡排序的次数,元素个数很大,不能用n^2的冒泡排序计算。

解析:这题实际上就是求逆序对的个数,可以用归并排序的方法,我这里用另一种方法写,bit树+离散化。由于元素的值可以达到很大,但元素个数最多只有500000个,可以先对这些数排序,离散化一下,比如5个数:1 5 8  233333333 122222,排序后他们对应的标号可以是1 2 3 5 4;每次插入一个数时add(val,1),计算该数以及之前所有的数的个数sum(val);那么逆序对的个数=当前这个数的位置-sum(val); 扫一遍即可。

代码如下:

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<iterator>
#include<utility>
#include<sstream>
#include<iostream>
#include<cmath>
#include<stack>
using namespace std;
const int INF=1000000007;
const double eps=0.00000001;
typedef __int64 LL;
int N;
int A[500001],pos[500001],elem[500001];
int lowbit(int x){  return x&-x; }
int sum(int id)
{
    int ret=0;
    while(id>0){ ret+=elem[id]; id-=lowbit(id); }
    return ret;
}
void add(int id,int val)
{
    while(id<=N){ elem[id]+=val; id+=lowbit(id); }
}
vector<int> save;
int main()
{
    while(scanf("%d",&N)!=EOF&&N)
    {
        save.clear();
        memset(elem,0,sizeof(elem));
        for(int i=1;i<=N;i++)
        {
            scanf("%d",&A[i]);
            save.push_back(A[i]);
        }
        sort(save.begin(),save.end());

        for(int i=1;i<=N;i++)
        {
            pos[i]=lower_bound(save.begin(),save.end(),A[i])-save.begin()+1;   //离散化
        }
        LL ans=0;
        for(int i=1;i<=N;i++)
        {
           add(pos[i],1);   //插入这个数
           ans+=i-sum(pos[i]);    //计算逆序对个数

        }
        cout<<ans<<endl;
    }
    return 0;
}
 
 

poj 2299 Ultra-QuickSort(归并排序或是bit 树+离散化皆可)

标签:

原文地址:http://www.cnblogs.com/wust-ouyangli/p/4761468.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!