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. 如何停止一个正在运行的java线程

    与此问题相关的内容主要涉及三部分:已废弃的Thread.stop().迷惑的thread.interrupt系列.最佳实践Shared Variable. 已废弃的Thread.stop() @Dep ...

  2. C++ 转型动作 尽量避免 以及 那些意想不到的威胁

    看完EffectiveC++的关于转型的章节,顿时认为周围的代码都处在悬崖边上~~ C的旧式转型:inta = 10; double b = (double)a; 对于C++的四种转型函数, cons ...

  3. AES算法工具类

    什么是对称加密算法? AES已经变成目前对称加密中最流行算法之一:AES可以使用128.192.和256位密钥,并且用128位分组加密和解密数据. 对称加密算法安全吗? 看过间谍局的知友们一定知道电台 ...

  4. [MAC OS] 常用工具

    1.Charles mac下的抓包.代理神器 比如我想本地配置 到我的开发机上面.我可以通过Charles 下Tools  -> Map Remote 配置跳转. 2.Postman chrom ...

  5. 【C++ Primer】用于大型程序的工具

    1. 异常处理 异常以类似于将实參传递给函数的方式抛出和捕获.异常可以是可传给非引用实參的随意实參的类型,这意味着必须可以复制该类型的对象. 当抛出一个表达式的时候,被抛出对象的静态编译时类型将决定异 ...

  6. C++ Jsoncpp源代码编译与解析Json

    1.Json 数据表示方式介绍 这个可以看之前的一个文章里面有说明:Java解析(读取)Json数据 2.C++ Jsoncpp 2.1 Jsoncpp介绍 (1)JsonCpp主要包含三种类型的cl ...

  7. [转贴] 数字证书及 CA 的扫盲介绍

    [略有删节] 为了达到普及的效果,俺会尽量用比较浅显,非技术的语言来讲清楚. ★先说一个通俗的例子 考虑到证书体系的相关知识比较枯燥.晦涩.俺先拿一个通俗的例子来说事儿.   ◇普通的介绍信 想必大伙 ...

  8. 测试用的数据库Transaction Log太大, 用于缩减它的脚本

    记在这里, 备用. select name, recovery_model_desc from sys.databases where name = 'WSS_Content_1000' USE WS ...

  9. PHP json_encode转换空数组为对象

    问题描述: php返回json格式的数据,当返回数据的为数组,且key为字符串时,json化后将返回jsonObject,但是如果是空数组,有可能返回的就是jsonArray,数据结构不一致导致端解析 ...

  10. ListView.MouseDoubleClick

    private void ruleListView_MouseDoubleClick(object sender, MouseButtonEventArgs e) { ListViewItem ite ...