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

    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
     
    Solution:
      题意就是给定$n$个数的序列($0$到$n-1$),求出序列的符合要求的排列中逆序对的个数最小值,(符合要求就是可以每次将序列第一位数移到序列最后一位或者不移)。
      思路就是先用树状数组求出原序列的逆序对个数$tot$,设首位数为$x$,则每次移动逆序对增加的个数为$x$后面比$x$大的数的个数(即$n-x$),每次减小的个数为$x$后面比$x$小的数的个数(即$x-1$)。
      那么移动前逆序对个数为$tot$,移动首位后逆序数$tot=tot-(x-1)+(n-x)$,于是枚举$n$次移动的情况(第$1$次表示不移,即原序列),更新最小值$ans$就行了。
      (坑点在于$HDU$上数据有多组,开始我还以为自己错了、查了半天~~手动滑稽~~)
    代码:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define il inline
    #define ll long long
    #define N 5005
    using namespace std;
    int n,a[N],c[N],ans=520520520,tot;
    il int gi(){
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        if(x=='-')x=getchar(),f=1;
        while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
        return f?-a:a;
    }
    il void update(int x,int k){
        while(x<=n){
            c[x]+=k;
            x+=x&-x;
        }
    }
    il int sum(int x){
        int ans=0;
        while(x){
            ans+=c[x];
            x-=x&-x;
        }
        return ans;
    }
    int main()
    {    
        while(scanf("%d",&n)==1){
            memset(c,0,sizeof(c));
            ans=520520520,tot=0;
            for(int i=1;i<=n;i++)a[i]=gi()+1;
            for(int i=n;i>=1;i--){
                update(a[i],1);
                tot+=sum(a[i]-1);
            }
            for(int i=1;i<=n;i++)tot=tot-(a[i]-1)+(n-a[i]),ans=min(ans,tot);
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    实用的.net小工具整理
    HTTP Analyzer——WEB调试代理
    JavaScript组件之JQuery(A~Z)教程(基于Asp.net运行环境)[示例代码下载]
    JAVA操作Excel表格
    java笔记一:类成员的初始化顺序
    javaMail发邮件
    初学hibernate框架
    Quartz在Spring中动态设置cronExpression (spring设置动态定时任务)转帖
    JAVA WEB开发中处理乱码汇总
    抽象工厂之更换皮肤
  • 原文地址:https://www.cnblogs.com/five20/p/8869002.html
Copyright © 2011-2022 走看看