HDU 1394 Minimum Inversion Number(线段树+逆序数)
2015-08-03 19:37
381 查看
HDU 1394 Minimum Inversion Number(线段树+逆序数)
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
听过学长的讲课之后,还是不懂,后来发现自己把题意理解错了,orz。果然是被dp洗脑了,以为是求最大逆序数……研究了下别人的代码,发现其实很简单,和之前做的题差不多……代码如下~
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
听过学长的讲课之后,还是不懂,后来发现自己把题意理解错了,orz。果然是被dp洗脑了,以为是求最大逆序数……研究了下别人的代码,发现其实很简单,和之前做的题差不多……代码如下~
#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; }
相关文章推荐
- Python中的print语句
- Sort List
- UIRefreshControl 实现UITableView的下拉刷新
- 风
- 响应式网站的开发
- 用中国视角解读早期希腊哲学
- hadoop 安装配置
- HDU 1312 Red and Black【递归】
- Java基础知识
- 机器学习算法总结(目录框架)
- Makefile经典教程(掌握这些足够)
- Red and Black
- poj-1860 Currency Exchange
- 关于三星某些系列笔记本电脑无法安装Windows10的原因及解决办法
- 设计模式 迪米特法则
- 【linux高级程序设计】(第十三章)Linux Socket网络编程基础 4
- Redis服务器剖析
- 简单登陆页面的创建(页面跳转.键盘回收.实现换行.清除textField中的文字)
- python常用函数
- 初窥Linux 之 我最常用的20条命令