http://acm.hdu.edu.cn/showproblem.php?pid=1394
Minimum Inversion Number
Problem Description
The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.
For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:
a1, a2, ..., an-1, an (where m = 0 - the initial seqence)
a2, a3, ..., an, a1 (where m = 1)
a3, a4, ..., an, a1, a2 (where m = 2)
...
an, a1, a2, ..., an-1 (where m = n-1)
You are asked to write a program to find the minimum inversion number out of the above sequences.
Input
The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.
Output
For each case, output the minimum inversion number on a single line.
Sample Input
10
1 3 6 9 0 8 5 7 4 2
Sample Output
16
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define N 5005 6 #define lson rt<<1,l,m 7 #define rson rt<<1|1,m+1,r 8 struct node 9 { 10 int l,r,value; 11 }tree[N<<2]; 12 int a[N]; 13 /* 14 求移位后的最小逆序数 15 Update单点增减 16 Query区间求和 17 */ 18 void Build(int rt,int l,int r) 19 { 20 tree[rt].l=l; 21 tree[rt].r=r; 22 tree[rt].value=0; 23 if(l==r) return ; 24 int m=(l+r)>>1; 25 Build(rt<<1,l,m); 26 Build(rt<<1|1,m+1,r); 27 } 28 29 void Update(int rt,int num) 30 { 31 if(tree[rt].l==num&&tree[rt].r==num){ 32 tree[rt].value=1; 33 return ; 34 } 35 int m=(tree[rt].l+tree[rt].r)>>1; 36 if(num<=m) Update(rt<<1,num); 37 else Update(rt<<1|1,num); 38 tree[rt].value=tree[rt<<1].value+tree[rt<<1|1].value; 39 } 40 41 int Query(int rt,int l,int r) 42 { 43 /* 44 画个图就明白了,搜寻的区间为[l,r],m代表当前节点的左儿子和右儿子的分支 45 如果左儿子有包含该区间的元素,即l<=m,那么就要继续递归搜寻左儿子 46 如果右儿子有包含该区间的元素,即m<r,那么就要继续递归搜寻右儿子 47 当当前的节点的区间被搜寻的区间[l,r]覆盖的话,就说明该段区间完全在[l,r]里面 48 那么返回该节点的值 49 */ 50 if(l<=tree[rt].l&&tree[rt].r<=r){ 51 return tree[rt].value; 52 } 53 else{ 54 int m=(tree[rt].l+tree[rt].r)>>1; 55 int s1=0,s2=0; 56 if(l<=m) s1=Query(rt<<1,l,r); 57 if(r>m) s2=Query(rt<<1|1,l,r); 58 return s1+s2; 59 } 60 } 61 62 int main() 63 { 64 int n; 65 while(~scanf("%d",&n)){ 66 Build(1,1,n); 67 int sum=0; 68 for(int i=0;i<n;i++){ 69 scanf("%d",&a[i]); 70 a[i]++; 71 sum+=Query(1,a[i]+1,n); 72 Update(1,a[i]); 73 } 74 int res = sum; 75 for(int i=n-1;i>=0;i--){ 76 sum=sum-(n-a[i])+(a[i]-1); 77 if(sum<res) res=sum; 78 } 79 printf("%d\n",res); 80 } 81 return 0; 82 }