minimum inversion number:最小逆序数
Minimum Inversion Number
Time Limit: 2000/1000MS (Java/Others) Memory Limit: 65536/32768 K
(Java/Others)
Total Submission(s):
9367 Accepted Submission(s):
5754
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
ZOJ
Monthly, January 2003
Recommend
Ignatius.L
来源: <http://acm.hdu.edu.cn/showproblem.php?pid=1394>
先建一个空树;
逐个插入值(即输入的一个值)
1 3 6 9 0 8 5 7 4
2
插入x时 查询已经插入的线段中(x+1,n-1)之间元素的个数
如:
插入 1 时 查询 已经插入的数中2-9 之间元素的个数
v1=0
插入 3 时 查询 已经插入的数中4-9 之间元素的个数 v2=0
插入 6 时 查询 已经插入的数中7-9之间元素的个数
v3=0
插入 9 时 查询 已经插入的数中10-9之间元素的个数 v4=0
插入 0 时 查询 已经插入的数中1-9之间元素的个数
v5=4
插入 8 时 查询 已经插入的数中9-9之间元素的个数 v6=1
……
插入 2 时 查询
已经插入的数中3-9之间元素的个数 v9=7
累加v1……v9 =sum =22 即最初序列逆序数为22
线段树在这里的作用是求出 最初序列的逆序数
接下来求最小逆序数
在序列 var= 0,1,2……n-1 中
比0小的个数 = 0 比0大的个数 n-1-0
比1小的个数 = 1 比1大的个数 n-1-1
……
比vi小的个数 = var 比vi大的个数 n-1-var
把第一个数var移动到后面
比vi小的数var个就都不构成逆序了 逆序数-var
比vi大的数n-1-var个构成逆序
逆序数+(n-1-var)
所以
逆序数=逆序数+n-1-var-var
循环移动n次,记录最小值,即为所求。
#include<stdio.h>
#include <algorithm>
using namespace std;
#define MAXN 50000
struct
Node{
int var;
int number;
};
Node
seq[MAXN*4];
void pushUp(int index){
seq[index].number=seq[index*2].number+seq[index*2+1].number;
}
void build(int
l,int r,int index){
seq[index].number=0;
if(l==r){
return ;
}
int mid=(l+r)/2;
build(l,mid,index*2);
build(mid+1,r,index*2+1);
}
int
Query(int from ,int to ,int
l,int r,int index){
int sum=0;
if(from<=l&&to>=r){
return
seq[index].number;
}
int mid=(l+r)/2;
if(from <=mid)
sum+=Query(from,to,l,mid,index*2);
if(to>mid)
sum+=
Query(from,to,mid+1,r,index*2+1);
return sum;
}
void
update(int p,int l,int
r,int index){
if(l==r){
seq[index].number++;
return ;
}
int mid = (l + r) /
2;
if (p <= mid)
update(p ,
l,mid,index*2);
else
update(p ,
mid+1,r,index*2+1);
pushUp(index);
}
int
main(){
int n;
while (~scanf("%d",&n))
{
build(0,n-1,1);
int sum=0;
for(int i=0;i<n;i++){
scanf("%d",&seq[i].var);
sum+= Query(seq[i].var+1,n-1,0,n-1,1);
update(seq[i].var,0,n-1,1);
}
//
printf("%d\n",sum);
int ans =
sum;
for (int
i = 0 ; i <
n ; i ++) {
sum
+= n - seq[i].var
- seq[i].var - 1;
ans =
min(ans , sum);
}
printf("%d\n",ans);
}
return 0;
}
【线段树】HDU 1394 Minimum Inversion Number