ACM暑期集训26

Minimum Inversion Number

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


 

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

分析:

可利用归并排序求出第一次的逆序数和,在用下面的公式求解最小的逆序数和;

如果每次都进行如上操作,那么最多进行n-1次后会与原序列重合;

这个序列的元素是从0---(n-1),当某个元素位于首位置时,其本身的数值就是后面的逆序个数;

每次将它移至末尾,原来的逆序即变成了正序,正序变逆;由此可得 sum=sum-a[i]+(n-a[i]-1);

#include <iostream>
#include <cstdio>
#include <cstring>
#include <math.h>
#include <algorithm>
using namespace std;
#define Min(a,b)(a<b?a:b)
const int maxn=5050;
int a[maxn],b[maxn],c[maxn];
int sum;

void Merge(int begin,int mid,int end){
    int i=begin,j=mid+1,pos=begin;
    while(i<=mid && j<=end){
        if(a[i]<=a[j]){
            b[pos++]=a[i++];
        }else{
            b[pos++]=a[j++];
            sum+=mid-i+1;//求逆序数
        }
    }
    while(i<=mid) b[pos++]=a[i++];
    while(j<=end) b[pos++]=a[j++];
    for(int i=begin,j=begin;i<=end;i++,j++)
        a[i]=b[j];
}

void Sort(int begin,int end){
    if(begin<end){
        int mid=(begin+end)/2;
        Sort(begin,mid);
        Sort(mid+1,end);
        Merge(begin,mid,end);
    }
}
int main(){
        int n;
        while(~scanf("%d",&n))
        {
            int ans;
        sum=0;
        for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                c[i]=a[i];
            }
            Sort(1,n);
        ans=sum;
        for(int i=1;i<=n;i++)
        {
            sum=sum-c[i]+(n-c[i]-1);
            ans=Min(ans,sum);
        }
        printf("%d\n",ans);
        }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41383801/article/details/81866314
今日推荐