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;
}