Minimum Inversion Number

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

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
 
Author
CHEN, Gaoli
 
Source
 
       求逆序数,这道题花了我一下午的时间去看线代,不过还好总算做出了....切克闹,切脑壳...
下 面来详细讲讲过程吧...
        首先,我求出了 Simple output 给出的 序列的 逆序数为22 这是没有错的,但是输出却为16,当时我这个小脑袋呀,真是....泪崩了呀!. 
 然后我就在这里纠结呀...哎,由于英语不是很好,居然没有读懂这句话的意思.....这是啥情况 ,妈蛋呀!
     out of the above sequences.  ------>从上面的式子中找出最小的逆序数...
     明白了这句话,下面就好办了..
    最后就是一点要说的是... 对于逆序数,如果存在左右顶端对调,并且这个序列是连续的..
是可以总结出规律的,,
看代码就知道了。。
                             time   300+ms....   c++ 
 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define maxn 5000
int a[maxn+];
int bb[maxn+]; //存储单个元素的逆序数
int main()
{
int n,i,j,tol;
while(scanf("%d",&n)!=EOF)
{
memset(bb,,sizeof(bb));
for(i=;i<n;i++)
{
scanf("%d",a+i);
for(j=i-;j>=;j--)
{
if(a[i]>a[j]&&bb[j]==) break;
if(a[i]<a[j])bb[i]++;
}
}
tol=;
for(i=;i<n;i++) //求出逆序数
tol+=bb[i];
int res=tol;
for(i=;i<n;i++)
{
tol+=n-*a[i]- ;
if(res>tol)
res=tol;
}
printf("%d\n",res);
} return ;
}

运用递归调用版的归并排序

比如 5 4 3 2 1 《5 ,4》,《3 ,2》  --》+ 2

 4 5 2 3 1
4 5 2 3  ---》 2 +2=4;
2 3 4 5 1 --》 4
10
运用这个原理便可以得到结果,代码如下:
 #include<string.h>
#include<stdlib.h>
#include<stdio.h>
#define maxn 5000
int aa[maxn+];
int bb[maxn+];
int nn,tol=;
void mergec(int low ,int mid ,int hight )
{
int i,j,k;
int *cc = (int *)malloc(sizeof(int)*(hight-low+));
i=low;
j=mid;
k=;
while( i<mid&&j<hight )
{
if(aa[i]>aa[j])
{
cc[k++]=aa[j++];
tol+=mid-i;
}
else
cc[k++]=aa[i++];
}
for( ; i<mid ;i++)
cc[k++]=aa[i];
for( ; j<hight ; j++)
cc[k++]=aa[j];
k=;
for(i=low;i<hight;i++)
aa[i]=cc[k++];
free( cc );
}
/*用递归求解归并排序无法求逆序数*/
void merge_sort(int st,int en)
{
int mid;
if(st+<en)
{
mid=st+(en-st)/;
merge_sort(st,mid);
merge_sort(mid,en);
mergec(st,mid,en);
}
}
int main()
{
int i,res;
// freopen("test.in","r",stdin);
while(scanf("%d",&nn)!=EOF)
{
tol=;
for(i=;i<nn;i++){
scanf("%d",aa+i);
bb[i]=aa[i];
}
merge_sort(,nn);
res=tol;
//printf("tol=%d\n",res);
for(i=;i<nn-;i++)
{
tol+=nn-*bb[i]-;
if(res>tol) res=tol;
}
printf("%d\n",res);
}
return ;
}

接下来是非递归调用....版的归并排序

 #include<string.h>
#include<stdlib.h>
#include<stdio.h>
#define maxn 5000
int aa[maxn+];
int bb[maxn+];
int nn,tol=;
void mergec(int low ,int mid ,int hight )
{
int i,j,k;
int *cc = (int *)malloc(sizeof(int)*(hight-low+));
i=low;
j=mid;
k=;
while( i<mid&&j<hight )
{
if(aa[i]>aa[j])
{
cc[k++]=aa[j++];
tol+=mid-i;
}
else
cc[k++]=aa[i++];
}
for( ; i<mid ;i++)
cc[k++]=aa[i];
for( ; j<hight ; j++)
cc[k++]=aa[j];
k=;
for(i=low;i<hight;i++)
aa[i]=cc[k++];
free( cc );
} /*----------------------华丽丽的分割线--------------------------------*/
void merge_sort( int st , int en )
{
int s,t,i;
t=;
while(t<=(en-st))
{
s=t;
t=s*; //表示两个s的长度
i=st;
while(i+t<=en){
mergec(i,i+s,i+t);
i+=t;
}
if(i+s<en)
mergec(i,i+s,en);
}
if(s<en-st)
mergec(st,st+s,en);
}
int main()
{
int i,res;
// freopen("test.in","r",stdin);
while(scanf("%d",&nn)!=EOF)
{
tol=;
for(i=;i<nn;i++){
scanf("%d",aa+i);
bb[i]=aa[i];
}
merge_sort(,nn);
res=tol;
//printf("tol=%d\n",res);
for(i=;i<nn-;i++)
{
tol+=nn-*bb[i]-;
if(res>tol) res=tol;
}
printf("%d\n",res);
}
return ;
}
 用树状数组...
代码:
 /*
用树状数组求逆序数
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define maxn 5000
int aa[maxn+];
int bb[maxn+];
int nn;
int lowbit(int k)
{
return k&(-k);
}
void ope(int x)
{
while(x<=nn)
{
aa[x]++;
x+=lowbit(x);
}
}
int sum(int x)
{
int ans=;
while(x>)
{
ans+=aa[x];
x-=lowbit(x);
}
return ans;
}
int main()
{ int i,res,ans;
//freopen("test.in","r",stdin);
while(scanf("%d",&nn)!=EOF)
{
memset(aa,,sizeof(aa));
res=;
for(i=;i<nn;i++)
{
scanf("%d",&bb[i]);
res+=sum(nn)-sum(bb[i]+);
ope(bb[i]+);
}
ans=res;
for(i=;i<nn;i++)
{
res+=nn--*bb[i];
if(ans>res)
ans=res;
}
printf("%d\n",ans);
}
return ;
}

HUDOJ-----1394Minimum Inversion Number的更多相关文章

  1. HDU 1394Minimum Inversion Number 数状数组 逆序对数量和

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...

  2. HDU 1394Minimum Inversion Number

    The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that ...

  3. 1394-Minimum Inversion Number

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...

  4. HDU 1394Minimum Inversion Number(线段树)

    题目大意是说给你一个数组(N个),没戏可以将其首部的k(k<N)个元素移动至尾部,这样总共会形成N个序列 现在要求这n个序列中逆序对数最少的那一个序列有多少个逆序对 最初的确是没太多思路,就算知 ...

  5. HDU 1394-Minimum Inversion Number(BIT)

    题意: 给你n个数字的序列 每次把第一个数字放到最后 得到一个新序列 一共有n个序列求这些序列中哪个序列含最小的总的逆序数 (输出最小总逆序数) 分析: 用BIT求出初始各数的逆序数,第一个数放最后它 ...

  6. HDU 1394 Minimum Inversion Number ( 树状数组求逆序数 )

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 Minimum Inversion Number                         ...

  7. HDU 1394 Minimum Inversion Number(最小逆序数 线段树)

    Minimum Inversion Number [题目链接]Minimum Inversion Number [题目类型]最小逆序数 线段树 &题意: 求一个数列经过n次变换得到的数列其中的 ...

  8. HDU 1394 Minimum Inversion Number(最小逆序数/暴力 线段树 树状数组 归并排序)

    题目链接: 传送门 Minimum Inversion Number Time Limit: 1000MS     Memory Limit: 32768 K Description The inve ...

  9. ACM Minimum Inversion Number 解题报告 -线段树

    C - Minimum Inversion Number Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d &a ...

  10. HDU-Minimum Inversion Number(最小逆序数)

    Problem Description The inversion number of a given number sequence a1, a2, ..., an is the number of ...

随机推荐

  1. Struts2 S标签 数目字格式化成金额输出(保留两位小数)

    JSP: <s:property value="%{formatDouble(price)}" /> Action:添加 //格式化数字显示 public String ...

  2. Excel向上取整

    CEILING函数语法:CEILING(number,significance)

  3. OBjective-C:在可变数组NSMutableArray中添加相同对象后,进行自定义的排序方式输出

    以下为自定义的排序方式的实现 #import "Person+Compare.h" @implementation Person (Compare) -(NSComparisonR ...

  4. SQL Server中数据的修改是如何落盘的?

    SQL Server 维护着一个叫做buffer cache的东西, 在buffer cache中SQL Server 读取必须被取回的data pages. 数据在修改时并不是直接写到磁盘上的, 而 ...

  5. scala 学习笔记八 简洁性

    Scala可以简洁地表示概念,有时甚至可以说过于简洁. 1.消除中间结果 在组合表达式中,最后一个表达式会变成整个表达式的结果.下面的例子中,值会被捕获到val result中,然后result从方法 ...

  6. scala多线程

    object Test { def main(args: Array[String]) { //创建线程池 val threadPool:ExecutorService=Executors.newFi ...

  7. 【架构】Kubernetes和Spring Cloud哪个部署微服务更好?

    Spring Cloud 和Kubernetes都自称自己是部署和运行微服务的最好环境,但是它们在本质上和解决不同问题上是有很大差异的.在本文中,我们将看到每个平台如何帮助交付基于微服务的架构(MSA ...

  8. 数字签名算法(C#)

    public static string GetSHA1Method(string strSource) { string strResult = ""; //Create Sys ...

  9. 防止excel数字变成科学计数法

    在网上查了很多资料知道解决办法大概有两个:一是在身份证字段前加个英文单引号,二是设置Excel的格式为文本格式. 我试用过第一种确实可以显示,但是有个“'”号在那里感觉确实不是很好,虽然听说不影响,但 ...

  10. C++ vector用法(转)

    在c++中,vector是一个十分有用的容器,下面对这个容器做一下总结. 1 基本操作 (1)头文件#include<vector>. (2)创建vector对象,vector<in ...