POJ 2299 Ultra-QuickSort 线段树/树状数组/并归排序
Language:
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
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 |
上一篇讲了线段树的一个解法,这次再讲一下树状数组的写法
这题题面的意思是给你一串数...每次交换相邻的两个数,求最少的交换次数...在这里也就是用到并归排序的求逆序数了....其实这题用并归排序是最好写的
题面和上一篇的基本相同,上次是求每个数之前有几个比它小的数,这次求逆序数就是求每个数之前有几个比它大的数...这不是很明显么...逆序排个序不就是前一题么
不过这题a[i]很大直接用线段树或树状数组储存肯定爆内存了,因此需要用离散化...
离散化的代码也很简单...
对a[i]排序以后...按顺序把值变成12345...再进行11映射 还原就行了
对树状数组的定义和实现我就不多说了 白书上都有
我解释一下我代码中的三个函数:
lowbit() 白书上有,就是那段数组所在的层数
一个是 discretization() 离散化,自己看不多说...
一个是modify() 更新, 每修改一个元素,更新的是C[] 这个辅助数组 , C[]辅助的意义是 : 对于每一个C[i]表示 数组中的某一段连续和...这段连续和的意义详情参照白书195页
最后一个是query() 查询 , 对于每一个i, 求a[i]之前的线段总和 ...这里因为modify操作每次都是对底层元素+1 ,所以查询到的值也就是比当前数据小的元素总数
先贴一个树状数组的代码:
/*Template*/ /*POJ 2299*/ #include <algorithm> #include <bitset> #include <complex> #include <deque> #include <functional> #include <iomanip> #include <iostream> #include <limits> #include <list> #include <map> #include <numeric> #include <queue> #include <set> #include <sstream> #include <stack> #include <string> #include <utility> #include <vector> #include <cassert> #include <cctype> #include <climits> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> using namespace std; //typedef long long LL; typedef __int64 LL; //Number #define EPS 1e-8 #define MAXN 500050 #define INF (1<<30) #define MOD 99991 //Math #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) int gcd(int a,int b){return b?gcd(b,a%b):a;} int lcm(int a,int b){return a*b/gcd(a,b);} //Segment Tree #define L(t) (t << 1) #define R(t) (t << 1 | 1) #define Mid(a,b) ((a+b)>>1) //BIT #define lowbit(a) (a&-a) struct node { int val,id; }a[MAXN]; int c[MAXN],resort[MAXN],n; void modify(int x ,int d) { while(x<=n) { c[x]+=d; x+=lowbit(x); } } LL query(int x) { LL ret = 0 ; while(x) { ret += c[x]; x-=lowbit(x); } return ret; } void discretization() //离散化 { int temp=a[1].val,p=1,i; for(i = 1 ;i <= n ; i++) { if(a[i].val!=temp) { a[i].val = ++p; temp = a[i].val; }else a[i].val = p; } for(i = 1 ; i <= n ;i++) { resort[a[i].id] = a[i].val; } } int cmp(node a,node b){return a.val>b.val;} int main() { // freopen("in.txt","r",stdin); // freopen("out.txt,"w",stdout); while(~scanf("%d",&n) && n) { memset(c,0,sizeof(c)); memset(resort,0,sizeof(resort)); LL sum = 0 ; int i; for(i = 1 ; i <= n ; i++) { scanf("%d",&a[i].val); a[i].id=i; } sort(a+1,a+n+1,cmp); discretization(); for(i = 1 ; i <= n ;i++) { sum+=query(resort[i]); modify(resort[i],1); } printf("%I64d\n",sum); } return 0; }
再贴一个线段树的代码
/*Template*/ /*POJ 2299*/ #include <algorithm> #include <bitset> #include <complex> #include <deque> #include <functional> #include <iomanip> #include <iostream> #include <limits> #include <list> #include <map> #include <numeric> #include <queue> #include <set> #include <sstream> #include <stack> #include <string> #include <utility> #include <vector> #include <cassert> #include <cctype> #include <climits> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> using namespace std; //typedef long long LL; typedef __int64 LL; //Number #define EPS 1e-8 #define MAXN 500050 #define INF (1<<30) #define MOD 99991 //Math #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) int gcd(int a,int b){return b?gcd(b,a%b):a;} int lcm(int a,int b){return a*b/gcd(a,b);} //Segment Tree #define L(t) (t << 1) #define R(t) (t << 1 | 1) #define Mid(a,b) ((a+b)>>1) //BIT #define lowbit(a) (a&-a) struct node { int l,r,val; }tree[MAXN*4]; struct node1 { int val,id; }a[MAXN]; int cmp(node1 a,node1 b){return a.val>b.val;} int n,resort[MAXN]; void build(int l,int r,int root) { tree[root].l = l; tree[root].r = r; tree[root].val = 0; if(l == r) return; int m = Mid(l,r); build(l,m,L(root)); build(m+1,r,R(root)); } void modify(int l,int r,int root,int val) { if(tree[root].l == l && tree[root].r == r) { tree[root].val+=val; return; } int m=Mid(tree[root].l,tree[root].r); if(r <= m) modify(l,r,L(root),val); else if(l > m) modify(l,r,R(root),val); else { modify(l,m,L(root),val); modify(m+1,r,R(root),val); } } int query(int x,int root) { if(tree[root].l == tree[root].r) return tree[root].val; int m=Mid(tree[root].l,tree[root].r); if(x<=m) return query(x,L(root)) + tree[root].val; else return query(x,R(root)) + tree[root].val; } void discretization() //离散化 { int temp=a[1].val,p=1,i; for(i = 1 ;i <= n ; i++) { if(a[i].val!=temp) { a[i].val = ++p; temp = a[i].val; }else a[i].val = p; } for(i = 1 ; i <= n ;i++) { resort[a[i].id] = a[i].val; } } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt,"w",stdout); while(~scanf("%d",&n) && n) { build(0,MAXN,1); memset(resort,0,sizeof(resort)); LL sum = 0 ; int i; for(i = 1 ; i <= n ; i++) { scanf("%d",&a[i].val); a[i].id=i; } sort(a+1,a+n+1,cmp); discretization(); for(i = 1 ; i <= n ;i++) { //cout<<resort[i]<<endl; sum+=query(resort[i],1); modify(resort[i],MAXN,1,1); } printf("%I64d\n",sum); } return 0; }