首页 > 代码库 > 【线段树】HDU 1394 Minimum Inversion Number
【线段树】HDU 1394 Minimum Inversion Number
minimum inversion number:最小逆序数
Minimum Inversion Number
Time Limit: 2000/1000 MS (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
逐个插入值(即输入的一个值)
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
……
插入 2 时 查询 已经插入的数中3-9之间元素的个数 v9=7
线段树在这里的作用是求出 最初序列的逆序数
接下来求最小逆序数
在序列 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;
}
来自为知笔记(Wiz)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。