POJ 2299 Ultra-QuickSort (树状数组求逆序数+离散化)
2014-07-31 23:40
501 查看
Ultra-QuickSort
Time Limit:7000MS Memory Limit:65536KB 64bit
IO Format:%I64d & %I64u
Submit Status Practice POJ
2299
Description
![](http://poj.org/images/2299_1.jpg)
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
Sample Output
题意:给你一组数,规定只能交换相邻的数,问最少交换多少次才能使这组数按升序排列。
心得:第一眼看题的时候,一想相邻元素之间交换,果断脑残地想到了冒泡啊,多聪明。。。一交TLE,这不是必须超嘛,要是不超,就是出题的二货了。后来,才知道这题也是求逆序数的,因为有多少逆序数,就必须交换多少次才能变成有序的。
分析:又是求逆序数问题。果断再次树状数组搞一下,如果数据不是很大, 可以一个个插入到树状数组中, 每插入一个数, 统计比他小的数的个数,对应的逆序为 i- getsum( data[i] ),其中 i 为当前已经插入的数的个数,sum(data[i])为比 data[i] 小的数的个数i- sum(data[i]) 即比 data[i] 大的个数, 即逆序的个数。
但是本题的问题是给的数据太大,如果数据比较大,就必须采用离散化方法。直接加入树状数组是搞不定的,今天又学了个好东西——离散化。
离散化:
一关键字的离散化方法:
所谓离散化也就是建立一个一对一的映射。 因为求逆序时只须要求数据的相应大小关系不变。
如: 10 30 20 40 50 与 1 3 2 4 5 的逆序数是相同的
定义一个结构体 struct Node{ int data; // 对应数据
int pos; // 数据的输入顺序 };
先对 data 升序排序, 排序后,pos 值对应于排序前 data 在数组中的位置。再定义一个数组 p
, 这个数组为原数组的映射。以下语句将按大小关系
把原数组与 1到 N 建立一一映射。
二关健字的离散方法:
先对第一个关键字进行离散化,然后对第二关键字排序。
本题是一个关键字的离散化。
AC代码:
Time Limit:7000MS Memory Limit:65536KB 64bit
IO Format:%I64d & %I64u
Submit Status Practice POJ
2299
Description
![](http://poj.org/images/2299_1.jpg)
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
题意:给你一组数,规定只能交换相邻的数,问最少交换多少次才能使这组数按升序排列。
心得:第一眼看题的时候,一想相邻元素之间交换,果断脑残地想到了冒泡啊,多聪明。。。一交TLE,这不是必须超嘛,要是不超,就是出题的二货了。后来,才知道这题也是求逆序数的,因为有多少逆序数,就必须交换多少次才能变成有序的。
分析:又是求逆序数问题。果断再次树状数组搞一下,如果数据不是很大, 可以一个个插入到树状数组中, 每插入一个数, 统计比他小的数的个数,对应的逆序为 i- getsum( data[i] ),其中 i 为当前已经插入的数的个数,sum(data[i])为比 data[i] 小的数的个数i- sum(data[i]) 即比 data[i] 大的个数, 即逆序的个数。
但是本题的问题是给的数据太大,如果数据比较大,就必须采用离散化方法。直接加入树状数组是搞不定的,今天又学了个好东西——离散化。
离散化:
一关键字的离散化方法:
所谓离散化也就是建立一个一对一的映射。 因为求逆序时只须要求数据的相应大小关系不变。
如: 10 30 20 40 50 与 1 3 2 4 5 的逆序数是相同的
定义一个结构体 struct Node{ int data; // 对应数据
int pos; // 数据的输入顺序 };
先对 data 升序排序, 排序后,pos 值对应于排序前 data 在数组中的位置。再定义一个数组 p
, 这个数组为原数组的映射。以下语句将按大小关系
把原数组与 1到 N 建立一一映射。
int id= 1; p[ d[1].pos ]= 1; for( int i= 2; i<= n; ++i ) if( d[i].data== d[i-1].data ) p[ d[i].pos ]= id; else p[ d[i].pos ]= ++id;
二关健字的离散方法:
先对第一个关键字进行离散化,然后对第二关键字排序。
本题是一个关键字的离散化。
AC代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <cstdlib> #include <ctime> #define INF 0x7fffffff #define LL long long using namespace std; const int maxn = 500000 + 10; const int maxx = 999999999; LL c[maxn]; struct node { int pos,val; }; node a[maxn]; int reflect[maxn]; int n; bool cmp(const node a,const node b) { return a.val<b.val; } int lowbit(int x) { return x & (-x); } void add(int x,int d) { while(x <= n) { c[x] += d; x += lowbit(x); } } int sum(int x) { int ret = 0; while(x > 0) { ret += c[x]; x -= lowbit(x); } return ret; } int main() { while(scanf("%d",&n)!=EOF && n) { LL cnt = 0; for(int i=1; i<=n; i++) { scanf("%d",&a[i].val); a[i].pos = i; } sort(a+1,a+1+n,cmp); for(int i=1; i<=n; i++) c[i]=0; for(int i=1; i<=n; i++) reflect[a[i].pos] = i; //离散化 for(int i=1; i<=n; i++) { add(reflect[i],1); cnt += i - sum(reflect[i]); //求逆序数 } printf("%lld\n",cnt); } return 0; }
相关文章推荐
- poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)
- poj 2299 Ultra-QuickSort 树状数组求逆序数 离散化
- POJ:2299 Ultra-QuickSort(树状数组+离散化+技巧+求逆序对)
- poj 2299 Ultra-QuickSort (离散化,树状数组,逆序对)
- POJ2299 Ultra-QuickSort(树状数组求逆序数+离散化)
- (POJ 2299)Ultra-QuickSort 树状数组求逆序对数 + 离散化
- poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)
- POJ 2299 Ultra-QuickSort(离散化+树状数组求逆序对)
- POJ 2299 Ultra-QuickSort 【树状数组 离散化 逆序对】
- POJ 2299 Ultra-QuickSort(树状数组+离散化 或 归并排序求逆序)
- POJ 2299 Ultra-QuickSort (树状数组求逆序数 || 线段树 +离散化)
- POJ 2299 Ultra-QuickSort 求逆序数 线段树或树状数组 离散化
- poj2299 Ultra-QuickSort(树状数组求逆序数,离散化)
- Poj 2299 - Ultra-QuickSort 离散化,树状数组,逆序对
- poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)
- poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)
- poj 2299 Ultra-QuickSort (树状数组+离散化)
- poj2299 Ultra-QuickSort (树状数组+离散化)
- POJ 2299 Ultra-QuickSort (树状数组 + 离散化)
- POJ 2299 Ultra-QuickSort(树状数组+离散化)