poj2299 Ultra-QuickSort
Ultra-QuickSort
Time Limit: 7000MS | Memory Limit: 65536K | |
Total Submissions: 61233 | Accepted: 22729 |
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.
Ultra-QuickSort produces the output
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
Source
表示我不看番
这张图是从YY那看到的
觉得很好看
还有
orz一拨题目旁边的马桶刷
嗯
非常草率的学了树状数组
还不是特别理解
等以后写多了应该就好了吧
然后照旧推一篇贼好的博客
And其实是两篇
然后就没什么好说的
注意一下减去小于它的数即为大于它的数即为逆序数
还有那个离散化刚开始也有点难理解
实际上就是把一堆很大很大的数按从小到大压成1~n
保持大小关系不变
aa[i]就表示离散化后的数
也就是原来i位置那个数在序列里排第几小
还有在一个序列里只能交换相邻两个元素
然后要求使序列从小到大排序的最小交换次数就是这个序列的逆序对数
因为交换相邻两个元素只会改变他们之间的大小关系
不会改变和其他元素的大小关系
即不改变和其他元素的逆序对
所以有多少个逆序对就至少需要交换多少次
然后就没啥了
#include<cstdio> #include<algorithm> #include<cstring> const int N=500005; struct node { int order,v; }a[N]; int n; int aa[N],c[N]; int lowbit(int i) { return i&-i; } bool cmp(node a,node b) { return a.v<b.v; } void update(int t,int value) { for(int i=t;i<=n;i+=lowbit(i)) c[i]+=value; } int getsum(int t) { int sum=0; for(int i=t;i>=1;i-=lowbit(i)) sum+=c[i]; return sum; } int main() { scanf("%d",&n); while(n) { for(int i=1;i<=n;i++) scanf("%d",&a[i].v),a[i].order=i; std::sort(a+1,a+1+n,cmp); memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) aa[a[i].order]=i; long long ans=0; for(int i=1;i<=n;i++) { update(aa[i],1); ans+=i-getsum(aa[i]); } printf("%lld\n",ans); scanf("%d",&n); } return 0; }