//POJ 2299 && ZOJ 2386 Ultra-QuickSort 线段树
/*
题意:
给一个序列,序列中的数都不重复,每次可以将序列中的两个数交换,
求将这个序列变成升序序列的最小交换次数
思路:
其实就是求这个序列的逆序数,离散化后边查询边插入即可
注意ans会爆int
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define N 500005
int sum[N<<2],a[N],b[N];
int n,cnt;
__int64 ans;
int cmp(const void *a,const void *b){
return *(int *)a -*(int *)b;
}
int Bin(int key){
int l = 1,r = cnt,mid;
while(r >= l){
mid = (l + r) >> 1;
if(b[mid] == key) return mid;
if(b[mid] < key) l = mid + 1;
else r = mid-1;
}
return -1;
}
void Build(){
memset(sum,0,sizeof(sum));
}
void Pushup(int rt){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void Update(int rt,int l,int r,int x){
if(l == r){
++sum[rt];
return;
}
int mid = (l + r) >> 1;
if(x <= mid) Update(lson,x);
else Update(rson,x);
Pushup(rt);
}
int Query(int rt,int l,int r,int L,int R){
if(L <= l && R >= r){
return sum[rt];
}
int mid = (l + r) >> 1;
int res = 0;
if(L <= mid) res += Query(lson,L,R);
if(R > mid ) res += Query(rson,L,R);
return res;
}
int main(){
int i;
while(scanf("%d",&n),n){
for(i = 1; i <= n; ++i){
scanf("%d",&b[i]);
a[i] = b[i];
}
qsort(b+1,n,sizeof(b[0]),cmp);
cnt = n;
Build();
ans = 0;
for(i = 1; i <= n; ++i){
int x = Bin(a[i]);
ans += Query(1,1,cnt,x,cnt);
Update(1,1,cnt,x);
}
printf("%I64d\n",ans);
}
return 0;
}
POJ 2299 && ZOJ 2386 Ultra-QuickSort 线段树
最新推荐文章于 2021-03-11 21:00:03 发布