poj2299 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.
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
这道题能够用线段树做,也能够用树状数组做。这道题树状数组快了一倍啊。。题目求的就是整个排序的逆序数,能够先离散化,然后每插入一个数,就推断前面有几个数(即比它小的数的个数)sum[i]。然后在这个数前且比这个数大的数的个数为i-sum[i],把它们都加起来即可了。逆序数的定义:排在pi前面而且比pi大的元素的个数称为元素pi的逆序数。
线段树代码:
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<algorithm> using namespace std; #define maxn 500010 __int64 sum; struct node{ int id,num,num1; }a[maxn]; struct edge{ int l,r,num; }b[4*maxn]; bool cmp(node a,node b){ return a.num<b.num; } bool cmp1(node a,node b){ return a.id<b.id; } void build(int l,int r,int i) { int mid; b[i].l=l;b[i].r=r;b[i].num=0; if(l==r)return; mid=(l+r)/2; build(l,mid,i*2); build(mid+1,r,i*2+1); } void question(int id,int i) { int mid; if(b[i].l==b[i].r){ b[i].num=1;return; } mid=(b[i].l+b[i].r)/2; if(id>mid)question(id,i*2+1); else { sum+=b[i*2+1].num;question(id,i*2); } b[i].num=b[i*2].num+b[i*2+1].num; } int main() { int n,m,i,j,c; while(scanf("%d",&n)!=EOF && n!=0) { build(1,maxn,1); for(i=1;i<=n;i++){ scanf("%d",&a[i].num); a[i].id=i; } sort(a+1,a+1+n,cmp); for(i=1;i<=n;i++){ a[i].num1=i; } sort(a+1,a+1+n,cmp1); sum=0; for(i=1;i<=n;i++){ question(a[i].num1,1); } printf("%I64d\n",sum); } return 0; }
树状数组代码:
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<algorithm> using namespace std; #define maxn 500005 struct node{ int id,num; }a[maxn]; int c[maxn]; bool cmp1(node a,node b){ return a.num<b.num; } bool cmp2(node a,node b){ return a.id<b.id; } int lowbit(int x){ return x&(-x); } void update(int pos,int num) { while(pos<=maxn){ c[pos]+=num;pos+=lowbit(pos); } } int sum(int pos) { int num=0; while(pos>0){ num+=c[pos];pos-=lowbit(pos); } return num; } int main() { int n,m,i,j; __int64 num; while(scanf("%d",&n)!=EOF && n!=0) { for(i=1;i<=n;i++){ scanf("%d",&a[i].num); a[i].id=i; } sort(a+1,a+1+n,cmp1); for(i=1;i<=n;i++) a[i].num=i; sort(a+1,a+1+n,cmp2); memset(c,0,sizeof(c)); num=0; for(i=1;i<=n;i++){ update(a[i].num,1); num+=i-sum(a[i].num); } printf("%I64d\n",num); } return 0; }