POJ 2299 Ultra-QuickSort 线段树/树状数组/并归排序

Language:
Ultra-QuickSort
Time Limit: 7000MS   Memory Limit: 65536K
Total Submissions: 31077   Accepted: 11082

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

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


posted @ 2013-03-10 14:49  Felix_F  阅读(154)  评论(0编辑  收藏  举报