HDOJ 1394 Minimum Inversion Number
2015-08-06 16:42
218 查看
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
本题就是求在a1,a2,…an的不断交换排列中,最小的逆序数之和,正解为按index建树,统计每个排列的逆序数之和。
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
本题就是求在a1,a2,…an的不断交换排列中,最小的逆序数之和,正解为按index建树,统计每个排列的逆序数之和。
///@zhangxiaoyu ///2015/8/1 ///此题正解为线段树,然而建树失败 ///由于数据小,暴力过了此题,暴力代码如下,以后把线段树的代码贴上 #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<vector> #include<stack> #include<map> #include<queue> #include<iostream> using namespace std; int a[5010]; int n; int solve1(int num)///调整一个排列后,比交换的数小的 { return num; } int solve2(int num)///调整后,num之前的逆序数的变化 { return n-num-1; } int main() { while(~scanf("%d",&n)) { int cnt=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); for(int j=1;j<i;j++) { if(a[j]>a[i]) cnt++; } } int ans=cnt; for(int i=1;i<=n;i++) { cnt=cnt-solve1(a[i])+solve2(a[i]); if(cnt<ans) ans=cnt; } printf("%d\n",ans); } return 0; } ///线段树版 #include<iostream> #include<stdio.h> #include<queue> #include<stack> #include<algorithm> #include<string.h> #include<string> #include<math.h> using namespace std; struct node { int left,right,sum; }tree[20000]; void build(int id,int l,int r) { tree[id].left=l; tree[id].right=r; tree[id].sum=0; if(l==r) return; int mid=(tree[id].left+tree[id].right)/2; build(2*id,l,mid); build(2*id+1,mid+1,r); }//建树过程不用多说了~ void update(int id,int val) { if(tree[id].left==val&&tree[id].right==val) { tree[id].sum=1;//当到达输入数字位置时sum变为1; return; } int mid=(tree[id].left+tree[id].right)/2; if(val<=mid) update(id*2,val);//递归更新数据 else update(id*2+1,val); tree[id].sum=tree[id*2].sum+tree[id*2+1].sum;//父节点为左右儿子的和 } int query(int id,int l,int r) { if(tree[id].left>=l&&tree[id].right<=r) { return tree[id].sum; } else { int mid=(tree[id].left+tree[id].right)/2; int ans=0; if(l<=mid) ans+=query(id*2,l,r); if(mid<r) ans+=query(id*2+1,l,r); return ans; } }//参照了线段树区间和的模板 int main() { int n; while(scanf("%d",&n)!=EOF) { build(1,0,n-1); int ans=0; int a[5005]; for(int i=0;i<n;i++) { scanf("%d",&a[i]); ans+=query(1,a[i]+1,n-1);//每次输入以后求一次该数的逆序数,最终和即为所有逆序数的和 update(1,a[i]);//更新树 } int Min=ans; for(int i=0;i<n;i++) { ans=ans-a[i]+(n-1-a[i]);//删除第i个数,会减少a[i]个逆序数,因为只有n-1个数,所以增加n-1-a[i]个逆序数; Min=min(Min,ans); } printf("%d\n",Min); } return 0; }
相关文章推荐
- WinDbg学习笔记(转)
- Android基本调试方法
- PHP批量去除文件头部Bom信息
- 常见的编译C++代码时的英文错误提示
- Objective-C Runtime 运行时之二:成员变量与属性
- 链式队列
- Android 内存使用分析 Investigating Your RAM Usage
- java使用Redis4--主从复制
- 在mac下设置环境变量
- Network of Schools---poj1236(强连通分量)
- 微信开发接入参考
- setTimeout和setInterval定时器
- URAL 1034. Queens in Peaceful Positions
- AJAX异步加载实例
- easyUI 1.4版本 easyui-numberbox输入不了小数点bug
- Linux学习(三) 展讯Android 4.0编译 -- Makefile
- poj-1094-Sorting It All Out-拓扑排序
- android 多媒体几个不错的博客
- 阅读《游戏引擎架构》的思考1:BSP分割在游戏引擎中的应用
- python独立脚本调用django settings