首页 > 代码库 > 【线段树】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
插入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;

}



































来自为知笔记(Wiz)