循环串的最小逆序(hdu 1394)

来源:互联网 发布:学习软件大全下载 编辑:程序博客网 时间:2024/06/06 05:58

Minimum Inversion Number

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


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
101 3 6 9 0 8 5 7 4 2
 

Sample Output

16

#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N=5005;struct NOde{    int l,r,mid,m;}node[4*N];void build(int l,int r,int k){    node[k].l=l;    node[k].r=r;    node[k].mid=(l+r)/2;    node[k].m=0;                  //存l-r范围内存在几个数字     if(l==r) return;    build(l,node[k].mid,k*2);    build(node[k].mid +1,r,k*2+1);}void update(int n,int k){    if(node[k].l==node[k].r)    {        node[k].m++;        return;    }    if(n<=node[k].mid) update(n,k*2);    else update(n,k*2+1);    node[k].m=node[k*2].m+node[k*2+1].m;} int find(int l,int r,int k){    if(l<=node[k].l&&r>=node[k].r)              {        return node[k].m;    }    int ret=0;    if(l<=node[k].mid) ret=ret+find(l,r,k*2);    if(r>node[k].mid) ret=ret+find(l,r,k*2+1);    return ret;                                  }int main(){    int n,num[N],sum,t;    while(~scanf("%d",&n))    {        build(1,n,1);                      //建树         sum=0;        for(int i=0;i<n;i++)        {            scanf("%d",&num[i]);            num[i]++;            int x=0;                         //每次都为0             if(num[i]!=n)            x=find(num[i]+1,n,1);            sum=sum+x;            update(num[i],1);        }        t=sum;        for(int i=n-1;i>=0;i--)                  //不懂         {            sum=sum-(n-num[i])+(num[i]-1);       //不懂             t=min(t,sum);                       //求最小值         }        printf("%d\n",t);    }    return 0;}


0 0
原创粉丝点击