您的位置:首页 > 产品设计 > UI/UE

POJ 2299 Ultra-QuickSort(离散化+树状数组求逆序对)

2016-08-03 10:49 681 查看
Ultra-QuickSort

Time Limit: 7000MS Memory Limit: 65536K
Total Submissions: 54900 Accepted: 20189
Description


In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is
sorted in ascending order. For the input sequence 
9 1 0 5 4 , 

Ultra-QuickSort produces the output 
0 1 4 5 9 . 

Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence. 
Input

The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence
element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.
Output

For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.
Sample Input
5
9
1
0
5
4
3
1
2
3
0

Sample Output
6
0

一题意:

给定了一种排序方式,通过交换相邻的两个元素的位置达到排序的效果,经过一番思考后会发现,一个排好序的队列事实上是一个完全顺序的队列,所以如果我们希望通过交换的方式来达到排序的效果那么对于每个元素来说已定要和他的所有逆序的数交换位置,且发现每次叫唤位置并不会对其他逆序对发生变化(因为交换的只是相邻元素,位置的改变只发生在这两者之间),所以我们推断出需要交换的总次数就是逆序对的数量。

二用树状数组求逆序对

思路很简单,逆序对就是一个元素之前的并且比这个元素大数构成的点对,那么用树状数组来统计逆序对我们需要换一个思路,倒着来搞,统计每个元素之后会出现多少个比这元素小的数,具体方法是:我们从字符串的尾部开始把元素x加入到树状数组位置x,中并赋值1,然后再通过树状数组的强项求和来统计一个元素之后有多少比他小的数,就是逆序对啦

三数据的离散化

因为树状数组要有位置x,所以我们需要把树状数组的大小开到和x的上限一样大,但是本题中上线回达到999,999,999,但是只有50000个不同的数字,浪费的大量空间和时间不说,也开不了这么大啊,所以我们使用离散化的思想,把这500000个不同的数的数值都压缩到500000中来(因为我们并不关心这个数据到底是多少,只关心他们之间的大小关系),我们利用一个结构来保存原来的位置(复原时用到)和原值(排序时用到),然后根据val来排序,然后把排序的序号当做其值放在val中,然后根据pos再复原到reflect中就可以了

//
//  main.cpp
//  POJ 2299
//
//  Created by 张嘉韬 on 16/8/3.
//  Copyright © 2016年 张嘉韬. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=500000+10;
ll  c[maxn];
int reflect[maxn];
struct Node
{
int val;
int pos;
}Nodes[maxn];

bool cmp(const Node& a, const Node& b)
{
return a.val < b.val;
}

inline ll lowbit(ll  x)
{
return (x&-x);
}
ll  sum(ll x)
{
ll temp=0;
for(ll  i=x;i;i-=lowbit(i))
temp+=c[i];
return temp;
}
void add(ll x,int value)
{
for(ll i=x;i<=maxn;i+=lowbit(i))
c[i]+=value;
}
int main(int argc, const char * argv[]) {
//freopen("/Users/zhangjiatao/Documents/暑期训练/input.txt","r",stdin);
int n;
while(scanf("%d",&n)==1)
{
if(n==0) break;
memset(c,0,sizeof(c));
memset(reflect,0,sizeof(reflect));
ll  ans=0;

for(int i=1;i<=n;i++)
{
scanf("%d",&Nodes[i].val);
Nodes[i].pos=i;
}

sort(Nodes + 1, Nodes + n + 1, cmp);
for(int i=1;i<=n;i++) reflect[Nodes[i].pos]=i;
for(int i=n;i>=1;i--)
{
ans+=sum(reflect[i]+1);
add(reflect[i]+1,1);
}
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: