标签:style io os for sp log on c amp
利用线段树在nlogn的时间复杂度内求一段数的逆序。
由于给的序列是由0 ~ n -1组成的,求出初始的逆序之后可以递推出移动之后的逆序数。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 5555;
int tree[maxn << 2];
int n;
void BuildTree(int L,int R,int pos){ //建树
tree[pos] = 0;
if(L == R)
return ;
int m = (L + R) >> 1;
BuildTree(L,m,pos << 1);
BuildTree(m + 1,R,(pos << 1)|1);
return ;
}
void UpDate(int aim,int L,int R,int pos){
if(L == R){
tree[pos] ++;
return ;
}
int m = (L + R) >> 1;
if(aim <= m)
UpDate(aim,L,m,pos << 1);
else
UpDate(aim,m + 1,R,(pos << 1)|1);
tree[pos] = tree[pos << 1] + tree[(pos << 1)|1];
return ;
}
int Query(int l,int r,int L,int R,int pos){
if(l <= L && R <= r)
return tree[pos];
int m = (L + R) >> 1;
int ans = 0;
if(l <= m)
ans += Query(l,r,L,m,pos << 1);
if(m < r)
ans += Query(l,r,m + 1,R,(pos << 1)|1);
return ans;
}
int main(){
while(scanf("%d",&n) != EOF){
BuildTree(0,n - 1,1);
int Sum = 0;
int x[maxn];
for(int i = 0 ; i < n ; i++){ //利用nlog(n)时间复杂度求逆序数
scanf("%d",&x[i]);
Sum += Query(x[i], n - 1,0,n - 1,1);
UpDate(x[i],0,n - 1,1);
}
int ans = Sum;
for(int i = 0 ; i < n; i++){
Sum = Sum + n - 2 * x[i] - 1;
ans = min(ans,Sum);
}
printf("%d\n",ans);
}
return 0;
}
【Hdu】Minimum Inversion Number(逆序,线段树)
标签:style io os for sp log on c amp
原文地址:http://blog.csdn.net/u013451221/article/details/39254643