zoukankan      html  css  js  c++  java
  • 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
     
    题意:一个长度为n的数列,可以变化为n个不同的数列(每次将首位元素放到最后一位),问这些序列中逆序数的个数最少为多少,逆序数:i < j and ai > aj,下标小于该元素的下标,值大于该元素。
     
    可以先利用线段树求出本身的序列中有多少逆序数,然后判断每个元素放到最后一位时的逆序个数是否小于本身序列的逆序个数,逐次更新。
     
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    const int INF=0x3f3f3f3f;
    const int N=5010;
    
    struct node
    {
        int left, right, num;
    }no[4*N];
    int Min;
    
    void Bulid(int left, int right, int root)
    {
        int mid;
    
        no[root].left = left;
        no[root].right = right;
        no[root].num = 0; 
    
        if (left == right) return ;
    
        mid = (left+right)/2;
    
        Bulid(left, mid, root*2);
        Bulid(mid+1, right, root*2+1);
    }
    
    void Insert(int p, int root) ///插入数据时就可以统计逆序数的个数
    {
        int mid;
    
        no[root].num++;
    
        if (no[root].left == no[root].right) return ;
    
        mid = (no[root].left+no[root].right)/2;
    
        if (p <= mid)
        {
            Min += no[root*2+1].num;
            Insert(p, root*2);
        }
        else Insert(p, root*2+1);
    }
    
    int main ()
    {
        int i, n, p[N], ans;
    
        while (scanf("%d", &n) != EOF)
        {
            Bulid(0, n-1, 1);
            Min = 0;
    
            for (i = 1; i <= n; i++)
            {
                scanf("%d", &p[i]);
                Insert(p[i], 1);
            }
    
            ans = Min;
    
            for (i = 1; i <= n; i++)
            {
                Min += (n-1-p[i]) - p[i]; ///首位移到最后一位时,逆序数加上那些比它大的数的个数,减去那些比它小的数的个数(因为该序列的元素都是0~n-1)
                ans = min(ans, Min);
            }
    
            printf("%d
    ", ans);
        }
    
        return 0;
    }
     
  • 相关阅读:
    EntityFramework4.5使用Expression类创建动态查询及动态查询导航属性
    EF 5.0 帮助类
    EF异常:“System.InvalidOperationException”类型的未经处理的异常在 mscorlib.dll 中发生
    EF框架学习手记
    Entity Framework 学习
    C#特性-表达式树
    LINQ to SQL 运行时动态构建查询条件
    一点css 基础
    JQuery 判断复选框是否选中
    Asp.Net Server.MapPath()用法
  • 原文地址:https://www.cnblogs.com/syhandll/p/4732602.html
Copyright © 2011-2022 走看看