zoukankan      html  css  js  c++  java
  • HDU 1394Minimum Inversion Number

    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. 

    InputThe 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. 
    OutputFor 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种序列,要求这n种序列中倒置数的最小个数,即满足下标i<j,a[i]>a[j]。

    其实说白了就是求不停倒置的最小逆序数

    求逆序数用线段树或者树状数组都是挺方便的,每次加一个数进去,看此时后面的数有几个。

    但这样肯定会超时,我们可以首先写出一开始的逆序数,发现每次倒置后,逆序数为减少a[i],而增加n-1-a[i]的。减少比它小的,增加比它大的

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=5005;
    int a[maxn<<4];
    int add[maxn];
    #define lson l,m,k<<1
    #define rson m+1,r,k<<1|1
    void hehe(int k)
    {
        a[k]=a[k<<1]+a[k<<1|1];
    }
    void build(int l,int r,int k)
    {
        a[k]=0;//先是假设这棵树都为0 
        if(l==r) return ;
        int m=(l+r)>>1;
        build(lson);
        build(rson);
    }
    int query(int x,int y,int l,int r,int k)
    {
        if(x<=l&&r<=y)
        return a[k];
        
        int m=(l+r)>>1;
        int s=0;
        if(x<=m) s+=query(x,y,lson);
        if(y>m) s+=query(x,y,rson);
        return s;
    }
    void update(int p,int l,int r,int k)
    {
        if(l==r)
        {
            a[k]++;//增加个数 
            return;
        }
        int m=(l+r)>>1;
        if(p<=m) update(p,lson);
        else update(p,rson);
        hehe(k);
    }
    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",&add[i]);
                sum+=query(add[i],n-1,0,n-1,1);
                update(add[i],0,n-1,1);
            }
            int minn=sum;
            for(int i=0;i<n;i++)
            {
                sum+=n-add[i]-add[i]-1;
                minn=min(minn,sum);
            }
            cout<<minn<<endl;
        }
        return 0;
    }
  • 相关阅读:
    DAY10-MYSQL表操作
    DAY10-MYSQL完整性约束
    DAY10-MYSQL数据类型
    DAY10-MYSQL存储引擎
    DAY10-MYSQL库操作
    017.2 基本数据类型对象包装类
    017.1 stringBuffer
    016.2 String
    16.1 eclipse设置
    015.5线程常见用法(面试题)
  • 原文地址:https://www.cnblogs.com/wpbing/p/9509445.html
Copyright © 2011-2022 走看看