Ultra-QuickSort(归并排序+离散化树状数组)

Ultra-QuickSort
Time Limit: 7000MS   Memory Limit: 65536K
Total Submissions: 50517   Accepted: 18534

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
题解:归并排序注意对dt主数组的更改,由于数据太大999999999所以要离散化
归并:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
typedef long long LL;
#define mem(x,y) memset(x,y,sizeof(x))
#define T_T while(T--)
#define F(i,x) for(i=1;i<=x;i++)
#define SI(x) scanf("%d",&x)
#define SL(x) scanf("%lld",&x)
#define PI(x) printf("%d",x)
#define PL(x) printf("%lld",x)
#define P_ printf(" ")
const int MAXN=500010;
int dt[MAXN],b[MAXN];
LL ans;
void mergesort(int l,int mid,int r){
	int ll=l,rr=mid+1,pos=l;
	while(ll<=mid&&rr<=r){
		if(dt[ll]<=dt[rr])b[pos++]=dt[ll++];
		else{
			ans+=rr-pos;
			b[pos++]=dt[rr++];
		}
	}
	for(int i=ll;i<=mid;i++)b[pos++]=dt[i];
	for(int i=rr;i<=r;i++)b[pos++]=dt[i];
	for(int i=l;i<=r;i++)dt[i]=b[i];
}
void ms(int l,int r){
	if(l<r){
		int mid=(l+r)>>1;
		ms(l,mid);
		ms(mid+1,r);
		mergesort(l,mid,r);
	}
}
int main(){
	int N;
	while(~scanf("%d",&N),N){
		int i,j;
		ans=0;
		F(i,N)
			SI(dt[i]);
			ms(1,N);
		PL(ans);puts("");
	}
	return 0;
}

  离散化树状数组跟归并原理相似;这个是用二分+离散化树状数组写的;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
typedef long long LL;
#define mem(x,y) memset(x,y,sizeof(x))
#define T_T while(T--)
#define F(i,x) for(i=0;i<x;i++)
#define SI(x) scanf("%d",&x)
#define SL(x) scanf("%lld",&x)
#define PI(x) printf("%d",x)
#define PL(x) printf("%lld",x)
#define P_ printf(" ")
const int MAXN=500010;
int a[MAXN],b[MAXN],tree[MAXN+1];
LL ans;
int lowbit(int x){return x&(-x);}
void add(int x){
	while(x<=MAXN){
		tree[x]++;
		x+=lowbit(x);
	}
}
int sum(int x){
	int sm=0;
	while(x>0){
		sm+=tree[x];
		x-=lowbit(x);
	}
	return sm;
}
int main(){
	int N;
	while(~scanf("%d",&N),N){
		int i,j;
		mem(tree,0);
		F(i,N)SI(a[i]),b[i]=a[i];
		sort(b,b+N);
		ans=0;
		F(i,N){
			int pos=lower_bound(b,b+N,a[i])-b;
			ans+=i-sum(pos);
			add(pos+1);
		}
		PL(ans);puts("");
	}
	return 0;
}

  其实用不到二分,结构体就妥了:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);
typedef long long LL;
#define mem(x,y) memset(x,y,sizeof(x))
#define T_T while(T--)
#define F(i,x) for(i=0;i<x;i++)
#define SI(x) scanf("%d",&x)
#define SL(x) scanf("%lld",&x)
#define PI(x) printf("%d",x)
#define PL(x) printf("%lld",x)
#define P_ printf(" ")
const int MAXN=500010;
int tree[MAXN+1];
LL ans;
int lowbit(int x){return x&(-x);}
struct Node{
	int v,p;
	friend bool operator < (Node a,Node b){
		return a.v<b.v;
	}
}a[MAXN];
void add(int x){
	while(x<=MAXN){
		tree[x]++;
		x+=lowbit(x);
	}
}
int sum(int x){
	int sm=0;
	while(x>0){
		sm+=tree[x];
		x-=lowbit(x);
	}
	return sm;
}
int main(){
	int N;
	while(~scanf("%d",&N),N){
		int i,j;
		mem(tree,0);
		F(i,N)SI(a[i].v),a[i].p=i;
		sort(a,a+N);
		ans=0;
		F(i,N){
			ans+=i-sum(a[i].p);
			add(a[i].p+1);
		}
		PL(ans);puts("");
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/handsomecui/p/5002137.html