HDU1394-Minimum Inversion Number

        http://acm.hdu.edu.cn/showproblem.php?pid=1394   

                  Minimum Inversion Number

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 8205    Accepted Submission(s): 5041

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
#include<stdio.h>
#define maxn 500004  
struct node  
{  
    int left,right;  
    int sum;  
};  
int val[maxn];
int n;
node tree[3*maxn];  
void build(int left,int right,int i)  
{  
    tree[i].left =left;  
    tree[i].right =right;  
    tree[i].sum =0;  
    if(tree[i].left ==tree[i].right )  
        return ;  
    build(left,(left+right)/2,2*i);  
    build((left+right)/2+1,right,2*i+1);  
}  
void update(int r,int j)
{
    tree[r].sum++;
    if(tree[r].left==tree[r].right)
        return ;
int mid=(tree[r].left +tree[r].right )/2;
      if(j<=mid)
          update(r*2,j);
      if(j>mid)
          update(r*2+1,j);
}
int getsum(int p, int left, int right)  
{  
    if (left > right)  
        return 0;  
    if (tree[p].left == left && tree[p].right == right)  
        return tree[p].sum;  
    int m = (tree[p].left + tree[p].right) / 2;  
    if (right <= m)  
        return getsum(p*2, left, right);  
    else if (left > m)  
        return getsum(p*2+1, left, right);  
    else return getsum(p*2, left, m) + getsum(p*2+1, m + 1, right);  
}  
int main()  
{  
    while (~scanf("%d",&n))  
    {  
        build(0,n - 1,1);  
        int i,sum =0,ans;  
        for (i = 1;i<= n; i++)  
        {  
            scanf("%d", &val[i]);  
            sum += getsum(1, val[i], n - 1);  
            update(1, val[i]);  
        }  
        ans = sum;  
        for (i = 1; i <= n; i++)  
        {  
            sum = sum + (n - val[i] - 1) - val[i];  
            ans = sum < ans ? sum : ans;  
        }  
        printf("%d\n", ans);  
    }  
    return 0;  
}  

 

 
posted @ 2013-10-30 19:32  疯狂的癫子  阅读(236)  评论(0编辑  收藏  举报