您的位置:首页 > 产品设计 > UI/UE

poj 2299 Ultra-QuickSort 二分+线段树求逆序数

2015-07-22 11:21 417 查看
Ultra-QuickSort

Time Limit: 7000MS Memory Limit: 65536K
Total Submissions: 47564 Accepted: 17354
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


题意:给出一个序列,可以交换任意两个数,最终使得序列从小到大排序,求最少交换次数。

思路:一个数要交换的次数就是看他前面有几个数比它大,也就是它的逆序数。最终就是求所有数的逆序数之和。但是看题目条件n最大有50000,若每个逆序数都循环一遍,就是n*n肯定超时了,得改进。一个思路就是,先将数列排序,对于原始数列中每一个数,二分找出它在排序之后的位置p,然后插入到线段树中对应位置,那么每个数的逆序数就是查询[p,n]中有多少个数。

代码:

#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 500000+10
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

int n;
int sum[maxn<<2];
int b[maxn];
int a[maxn];

void pushUp(int rt){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}

void build(int l,int r,int rt){
if(l==r){
sum[rt] = 0;
return;
}
int m = (l+r) >> 1;
build(lson);
build(rson);
pushUp(rt);
}

void update(int p,int l,int r,int rt){
if(l==r){
sum[rt] = 1;
return;
}
int m = (l+r) >>1;
if(p<=m) update(p,lson);
else update(p,rson);
pushUp(rt);
}

int query(int L,int R,int l,int r,int rt){
if(L<=l && r<=R) return sum[rt];
int m = (l+r) >> 1;
int res = 0;
if(L<=m) res += query(L,R,lson);
if(R>m) res += query(L,R,rson);
return res;
}

int main(){
while(~scanf("%d",&n) && n){
build(0,n-1,1);
for(int i=0;i<n;i++){
scanf("%d",&b[i]);
a[i] = b[i];
}
sort(b,b+n);
long long ans = 0;
for(int i=0;i<n;i++){
int p = a[i];
int l=0,r=n,m;
while(l<r){
m = (l+r) >> 1;
if(b[m] > p) r = m;
else l = m+1;
}
int temp = query(r-1,n-1,0,n-1,1);
//printf("@@@%d %d\n",r-1,temp);
ans += temp;
update(r-1,0,n-1,1);
}
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: