poj_2299_Ultra-QuickSort_201407251113
2014-07-25 15:14
369 查看
Ultra-QuickSort
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
Sample Output
Time Limit: 7000MS | Memory Limit: 65536K | |
Total Submissions: 40253 | Accepted: 14515 |
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
SourceWaterloo local 2005.02.05 题目大意:给出长度为n的序列,每次只能交换相邻的两个元素,问至少要交换几次才使得该序列为递增序列。 解题思路:一看就是冒泡,交换一次记录一次就可以了但是n的范围达到50W,冒泡O(n^2)的复杂度铁定超时(即使有7000ms,其实这是一个陷阱,第一次做的就超时了)直接用快排又不符合题目的要求(相邻元素交换),快排是建立在二分的基础上的,操作次数肯定比在所要求的规则下的交换次数要更少 那么该怎么处理? 其实这题题目已经给出提示了:Ultra-QuickSort特殊的快排,能和快排Quicksort相媲美的就是归并排序Mergesort了,O(nlogn) 但是用归并排序并不是为了求交换次数,而是为了求序列的 逆序数(学过《线代》的同学应该很熟悉了)一个乱序序列的 逆序数 = 在只允许相邻两个元素交换的条件下,得到有序序列的交换次数 例如例子的9 1 0 5 4由于要把它排列为上升序列,上升序列的有序就是 后面的元素比前面的元素大而对于序列9 1 0 5 49后面却有4个比9小的元素,因此9的逆序数为41后面只有1个比1小的元素0,因此1的逆序数为10后面不存在比他小的元素,因此0的逆序数为05后面存在1个比他小的元素4, 因此5的逆序数为14是序列的最后元素,逆序数为0 因此序列9 1 0 5 4的逆序数 t=4+1+0+1+0 = 6 ,恰恰就是冒泡的交换次数PS:注意保存逆序数的变量t,必须要用long long(__int64)定义,int和long都是无法保存的。。。。会导致WA。注意long long(__int64)类型的输出必须使用指定的c格式输出,printf(“%I64d”,t);cout是无法输出__int64类型的序列数组s[]用int就足够了,每个元素都是小于10E而已#include <stdio.h> #include <string.h> #define MAXN 500050 int s[MAXN],temp[MAXN]; long long ans; void merge(int a[],int l,int mid,int r) { int i,j,k; i = k =l; j = mid+1; while(i<=mid && j<=r) { if(a[i]<a[j]) { temp[k++] = a[i]; i++; } else { temp[k++]=a[j]; j++; ans += mid-i+1; } } while(i<=mid) { temp[k++]=a[i]; i++; } while(j<=r) { temp[k++]=a[j]; j++; } for(i=l;i<=r;i++) { a[i] = temp[i]; //printf("%d ",temp[i]); } //printf("\n"); } void mergesort(int a[],int l,int r) { int mid=0; if(l<r) { mid = (l+r)>>1; mergesort(a,l,mid); //printf("A1A %d %d \n",l,mid); mergesort(a,mid+1,r); //printf("A2A %d %d \n",mid+1,r); merge(a,l,mid,r); //printf("A3A %d %d %d\n",l,mid,r); } } int main() { int n; while(scanf("%d",&n),n) { int i; for(i=1;i<=n;i++) scanf("%d",&s[i]); ans = 0; mergesort(s,1,n); printf("%I64d\n",ans); } return 0; }
//归并排序法
树状数组求解的思路:开一个能大小为这些数的最大值的树状数组,并全部置0。从头到尾读入这些数,每读入一个数就更新树状数组,查看它前面比它小的已出现过的有多少个数sum,然后用当前位置减去该sum,就可以得到当前数导致的逆序对数了。把所有的加起来就是总的逆序对数。题目中的数都是独一无二的,这些数最大值不超过999999999,但n最大只是500000。如果采用上面的思想,必然会导致空间的巨大浪费,而且由于内存的限制,我们也不可能开辟这么大的数组。因此可以采用一种称为“离散化”的方式,把原始的数映射为1-n一共n个数,这样就只需要500000个int类型的空间。离散化的方式:struct Node{int val;int pos;};Node node[500005];int reflect[500005];val存放原数组的元素,pos存放原始位置,即node[i].pos = i。把这些结构体按照val的大小排序。reflect数组存放离散化后的值,即reflect[node[i].pos] = i。这样从头到尾读入reflect数组中的元素,即可以保持原来的大小关系,又可以节省大部分空间。
代码如下:#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAXN 500050 typedef struct node { int val; int pos; }node; node s[MAXN]; int c[MAXN],reflect[MAXN],n; int cmp(const void *a,const void *b) { return (*(node *)a).val - (*(node *)b).val; } int lowbit(int i) { return i&(-i); } void add(int x) { while(x<=n) { c[x] += 1; x += lowbit(x); } } int getsum(int x) { int sum =0; while(x>0) { sum += c[x]; x -= lowbit(x); } return sum; } int main() { while(scanf("%d",&n),n) { int i,j; long long ans = 0; for(i=1;i<=n;i++) { scanf("%d",&s[i].val); s[i].pos=i; } qsort(s+1,n,sizeof(s[1]),cmp); //for(i=1;i<=n;i++) //printf("%d ",s[i].val); for(i=1;i<=n;i++) reflect[s[i].pos]=i;//离散化 for(i=1;i<=n;i++) c[i] = 0; for(i=1;i<=n;i++) { add(reflect[i]); ans += i-getsum(reflect[i]); } printf("%I64d\n",ans); } return 0; } //离散化 + 树状数组
相关文章推荐
- poj 2299 Ultra-QuickSort
- POJ 2299 Ultra-QuickSort (归并排序)
- poj 2299 Ultra-QuickSort
- poj 2299 Ultra-QuickSort
- POJ2299——Ultra-QuickSort
- POJ 2828 Buy Tickets&POJ 2299 Ultra-QuickSort
- POJ2299 Ultra-QuickSort
- POJ——T 2299 Ultra-QuickSort
- poj 2299 Ultra-QuickSort(归并排序)||(树状数组+离散化)
- Ultra-QuickSort(POJ 2299)
- POJ 2299 Ultra-QuickSort
- poj 2299 Ultra-QuickSort (树状数组解法)
- POJ 2299 Ultra-QuickSort (树状数组求逆序数 || 线段树 +离散化)
- POJ 2299 Ultra-QuickSort (求序列的逆序对数)
- poj 2299 Ultra QuickSort 树状数组+离散化
- Poj 2299 Ultra-QuickSort 求逆序数 4种方法总结
- POJ - 2299 Ultra-QuickSort解题报告
- POJ 2299 Ultra-QuickSort(逆序数)
- [树状数组 逆序对] poj 2299 Ultra-QuickSort
- POJ 2299 Ultra-QuickSort 快速排序求逆序对