poj 2299 Ultra-QuickSort

和小朋友排队时一样的题,线段树+离散化+逆序数,注意求的是交换几次,最后结果除2.


<span style="font-size:18px;">#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<vector>
#include<list>
#include<algorithm>
using namespace std;
#define MAX 500010
#define lson l,m,level*2
#define rson m+1,r,level*2+1
long long a[MAX];
long long b[MAX];
long long insert(long long l,long long r,long long level,long long x);
long long found(long long x);
struct node{
	long long x;
	long long l;
	long long h;
}num[MAX];
	long long n;
	long long tree[MAX*5];
int main(){

	scanf("%I64d",&n);
	while(n){
	 for(long long i=1;i<=n;i++){
	 	scanf("%I64d",&a[i]);
	 	b[i] = a[i];
	 	num[i].h = 0;
	 }
	 //离散化 
	 sort(b+1,b+1+n);
	 for(long long i=1;i<=n;i++){
	 	long long t = found(a[i]);
	 	a[i] = t;
	 	num[t].x = i;
	 	b[t]--;
	 }
	 //线段树插入 
	 memset(tree,0,sizeof(tree));
	 long long sum = 0;
	 for(long long i=1;i<=n;i++){
	 	num[a[i]].h = insert(1,n,1,a[i]);	//点插入(按照原顺序,计算比该点大的数的数目) 
	 	num[a[i]].l = a[i] - (num[a[i]].x - num[a[i]].h);
	 	sum += num[a[i]].h + num[a[i]].l;
	 } 
	 printf("%I64d\n",sum/2);
scanf("%I64d",&n);
}
	return 0;
}

long long insert(long long l,long long r,long long level,long long x){
	if(l==r&&l==x){
		tree[level] = 1;
		return 0;	//注意该点不计入 
	}
	long long m = (l+r)>>1;
	long long temp;
	if(x<=m){
		temp = insert(lson,x);
		temp += tree[level*2+1];	//加上比他大的数 
	}
	else if(x>m){
		temp = insert(rson,x);
	}
	tree[level] = tree[level*2] + tree[level*2+1];	//更新tree 
	return temp;
}
//二分 
long long found(long long x){
	long long l = 1,r = n;
	long long mid;
	while(l<r){
		mid = (l+r)/2;
		if(b[mid]==x){
			if(b[mid-1]!=x)	return mid;
			else	r = mid-1;
		}
		else if(b[mid]>x){
			r = mid-1;
		}
		else if(b[mid]<x){
			l = mid+1;
		}
	}
	return l;
}</span>


你可能感兴趣的:(线段树,poj,离散化,逆序数)