POJ 2299 Ultra-QuickSort(树状数组)

本文介绍了解决POJ2299问题的方法,该问题是求解最少相邻交换次数使序列升序。文章首先介绍了错误的快速排序思路,然后详细解释了使用树状数组的正确解法,并通过离散化处理大数据范围。

poj 2299

题目大意

给一组数,问最少经过多少次相邻交换可以将他们变成升序排列
n<500000;a[i]<999999999;

分析

【错误思路】一开始没仔细想太多拿着一个快排算法就开始写了,原本想的是,快排中第一个元素的右边比它小的一定会交换到它的右边,将快拍算法递归中的每一层的第一个元素右边比它小的数的个数加起来的和就是最终答案。样例是过了,其实这样是错误的。
在WA了之后改用树状数组写了一发结果RE,回去读题才注意到原来数的范围太大,我想到的是用map来实现离散化将这些数映射到1~500000的范围。TLE了几次,看别人的博客才发现不用map直接一个数组和结构体就能搞定,可能是这里用map效率有点低才超时吧。

代码

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<map>
#include<queue>
#include<algorithm>
using namespace std;
int n;
int a[500005];
long long int ans=0;
long long int C[500005];
int max_num;
map<int,int> Hash;
struct Node
{
      int val;
      int pos;
}node[500005];
int reflect[500005];
long long int Sum(int x)
{

      long long int ret=0;
      while(x>0)
      {
            ret+=C[x];
            x-=(x&(-x));
      }
      return ret;
}
void Add(int x,int m)
{
      while(x<=n)
      {
            C[x]+=m;
            x+=x&(-x);
      }
}
void Work()
{
      for(int i=1;i<=n;i++)C[i]=0;
      for(int i=n;i>=1;i--)
      {
            int t=reflect[i];
            ans+=Sum(t);
            Add(t,1);
      }
}
bool cmp(const Node& a, const Node& b)
{
       return a.val < b.val;
}
int main()
{
   while(scanf("%d",&n)!=EOF)
   {
       if(n==0)break;
       ans=0;
       max_num=0;
       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;
       Work();
       cout<<ans<<endl;
   }

}
//3 999999999 2 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值