poj2299 Ultra-QuickSort&&NYOJ117 求逆序数 (树状数组求逆序对数+离散化)+(归并排序)
2014-09-02 22:53
344 查看
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: 42087 | Accepted: 15296 |
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/* 之前用归并排序做,竟然超时。。。。很郁闷,明明可以的,,我也没再写归并排序,这个事树状数组做的、 加油!!! Time:2014-9-2 */ #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAX=500005; struct Node{ int val; int pos; }node[MAX]; int C[MAX],hash[MAX],N; bool cmp(const Node a,const Node b){ if(a.val==b.val) return a.pos<b.pos;//因为位置从小到大开始检索,将位置大的放到后边避免重复 return a.val<b.val;//此处排序不能等于,如果值相等,位置按从小到大 } int lowbit(int x){ return x&(-x); } void Modify(int x,int v){ while(x<=N){ C[x]+=v; x+=lowbit(x); } } int nSum(int x){ int sum=0; while(x>0){ sum+=C[x]; x-=lowbit(x); } return sum; } void solve(){ while(scanf("%d",&N),N){ for(int i=1;i<=N;i++){ scanf("%d",&node[i].val); node[i].pos=i;//标记值的位置 } sort(node+1,node+N+1,cmp);//值相等时,位置小的在前,检索的时候按位置从小到大检索, //如果位置从大到小,相同值的时候检索后边的时候会少掉前边的,这样求出来的i-nSum(hash[i])就会多一个,因为位置比它小的还没加到里边,树状数组是按位置来相加的 for(int i=1;i<=N;i++) hash[node[i].pos]=i;//将值位置标记为对应的hash值,将价值离散化,将把原来的位置按价值排序后的顺序进行标记,下边找逆序对的时候按原来的位置进行寻找 for(int i=1;i<=N;i++) C[i]=0; long long ans=0; for(int i=1;i<=N;i++){// i 表示位置,从第一个开始 Modify(hash[i],1); ans+=i-nSum(hash[i]);//排序方式可以使相同的值求逆序对为 0,将其减掉 //hash[i]表示第 i 个位置的hash值,用 i 减之前位置小于等于它的个数,就是比它大的个数 } printf("%lld\n",ans); } } int main(){ solve(); return 0; }
/* 以下为NYOJ117 的代码,代码一样 很费解的是,昨天写的归并排序代码,超时。。。。至今不知道为什么 Time:2014-9-3 0:09 */ #include<cstdio> #include<cstring> #include<climits> #include<algorithm> using namespace std; const int MAX=500000+20; int a[MAX<<1],t1[MAX],t2[MAX]; long long ans; void merge(int start,int end,int mid){ int i,j,k; for(k=0,i=start;i<=mid;i++) t1[k++]=a[i]; t1[k]=INT_MAX; for(k=0,i=mid+1;i<=end;i++) t2[k++]=a[i]; t2[k]=INT_MAX; i=j=0; for(k=start;k<=end;k++){ if(t1[i]<=t2[j]){ a[k]=t1[i++]; }else{ ans+=(mid-start+1-i); a[k]=t2[j++]; } } } void merge_sort(int start,int end){ if(end>start){ int mid=((start+end)>>1); merge_sort(start,mid); merge_sort(mid+1,end); merge(start,end,mid); } } void solve(){ int T,N; scanf("%d",&T); while(T--){ scanf("%d",&N); for(int i=0;i<N;i++) scanf("%d",&a[i]); ans=0; merge_sort(0,N-1); printf("%lld\n",ans); } } int main(){ solve(); return 0; }
/* 以下为超时代码,,我也不知道为什么。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。无语 */ #include<stdio.h> #include<string.h> #include<limits.h> const int MAX=500020; long long cnt; int a[MAX<<1],t1[MAX],t2[MAX]; void Merge(int start,int mid,int end){ int i,j,k; for(k=0,i=0;i<=mid;i++) t1[k++]=a[i]; t1[k]=INT_MAX; for(k=0,i=mid+1;i<=end;i++) t2[k++]=a[i]; t2[k]=INT_MAX;//将前后的最后一个设成无穷大,到了最后一个如果没有合并完,会一直合并 for(i=j=0,k=start;k<=end;k++){ if(t1[i]<=t2[j]){ a[k]=t1[i++]; }else{ cnt+=(mid-start+1-i); a[k]=t2[j++]; //如果前边比后边的大,由后边那个数与前边集合能组成的逆序对数为包括i--mid的个数 } } } void merge_Sort(int start,int end){ if(end>start){ int mid=(start+end)>>1; merge_Sort(start,mid); merge_Sort(mid+1,end); Merge(start,mid,end); } } void solve(){ int T,N; scanf("%d",&T); while(T--){ scanf("%d",&N); for(int i=0;i<N;i++) scanf("%d",&a[i]); cnt=0; merge_Sort(0,N-1); printf("%lld\n",cnt); } } int main(){ solve(); return 0; }
相关文章推荐
- Ultra-QuickSort---poj2299 (归并排序.逆序数.树状数组.离散化)
- POJ 2299 Ultra-QuickSort(树状数组+离散化 或 归并排序求逆序)
- (POJ 2299)Ultra-QuickSort 树状数组求逆序对数 + 离散化
- 【树状数组--求逆序数(离散化)】poj2299 Ultra-QuickSort
- 【树状数组】poj2299 Ultra-QuickSort(离散化+树状数组求逆序数)
- poj2299 Ultra-QuickSort(离散化+树状数组求逆序数)
- 【POJ】2299 - Ultra-QuickSort(离散化 & (树状数组 | 线段树))
- poj2299:Ultra-QuickSort(树状数组+离散化)
- poj 2299 Ultra-QuickSort(树状数组求逆序数+离散化)
- nyoj 117 求逆序数 【树状数组】+【离散化】
- Poj 2299 - Ultra-QuickSort 离散化,树状数组,逆序对
- POJ 2299 Ultra-QuickSort(归并排序,树状数组,离散化)
- NYOJ 117 求逆序数 (树状数组 + 离散化思路)
- nyoj 117 求逆序数【线段树 树状数组 归并排序】
- Ultra-QuickSort 学习归并排序(树状数组+离散化)
- Ultra-QuickSort(树状数组求逆序对数)
- POJ2299 Ultra-QuickSort(树状数组求逆序数+离散化)
- Ultra-QuickSort (poj 2299 归并排序 || 树状数组 求逆序对)
- POJ 2299 Ultra-QuickSort (树状数组求逆序数+离散化)
- POJ 2299 Ultra-QuickSort(离散化+树状数组求逆序对)