zoukankan      html  css  js  c++  java
  • HDU1394 Minimum Inversion Number

    /*
    求逆序数
    Minimum Inversion Number
    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 7097    Accepted Submission(s): 4333
    
    
    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
    
    */
    /*暴力解决*/
    #include <iostream>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    #include<string.h>
    #include<stdio.h>
    #include<stdlib.h>
    using namespace std;
    #define maxn  5100
    #define Max 100000000
    int main()
    {
        int sum[maxn],ans,i,j,n,num;
        while(~scanf("%d",&n))
        {
            ans=Max;
            num=0;
            for(i=1;i<=n;i++)
            scanf("%d",&sum[i]);
            for(i=1; i<=n; i++)
                for(j=i+1; j<=n; j++)
                {
                    if(sum[i]>sum[j])
                        num++;
                }
            for(i=1;i<=n;i++)
            {
                num=num+(n-sum[i])-(sum[i]+1);
                ans = min(ans,num);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    
    /*用线段树做*/
    #include <iostream>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    #include<string.h>
    #include<stdio.h>
    #include<stdlib.h>
    using namespace std;
    //#define maxn 50100
    const int maxn = 222222;
    #define lson l, m , rt<<1
    #define rson m+1 , r ,rt<<1|1
    int  sum[maxn<<2];
    void PushUP(int rt)
    {
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    void cre(int l,int r,int rt)
    {
        sum[rt]=0;
        if(l==r)
        {
            return ;
        }
        int m = (l+r)>>1;
        cre(lson);
        cre(rson);
        PushUP(rt);
    }
    void update(int p, int l,int r,int rt)
    {
        if(l==r)
        {
            sum[rt]++;
            return ;
        }
        int m = (l + r)>>1;
        if(p<=m) update(p,lson);
        else update(p,rson);
        PushUP(rt);
        // 和方法2对照发现两个递归有点区别,法2是先把根节点的和更新,而
        //法3是先更新叶子节点,然后反过来更新根节点
    }
    int qur(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&r<=R)
        {
            return sum[rt];
        }
        //大神是分数组的区间,而我们是分要求的区间,所以他是小于等于,真妙
        int m = (l + r)>>1;
        int ret = 0;
        if(L<=m)
            ret+=qur(L,R,lson);
        if(R>m)
            ret+=qur(L,R,rson);
        return ret;
    }
    int a[maxn];
    int main()
    {
        int n;
        while(~scanf("%d",&n))
        {
            cre(0,n-1,1);
            int sum=0;
            for(int i=0; i<n; i++)
            {
                scanf("%d",&a[i]);
                sum+=qur(a[i],n-1,0,n-1,1);
                update(a[i],0,n-1,1);
            }
            int ret =sum;
            for(int i=0; i<n; i++)
            {
                sum+=n-(a[i]+1)-a[i];
                ret=min(ret,sum);
            }
            printf("%d
    ",ret);
        }
        return 0;
    }
  • 相关阅读:
    beanstalkd 安装和配置
    vm虚拟机用批处理启动和关闭
    Windows设置VMware开机自动启动,虚拟机也启动
    批处理脚本学习笔记1--vmware虚拟机启停控制
    Shell中uname命令查看系统内核、版本
    SHELL脚本里执行的东西需要多次回车确认,怎么实现自动回车确认?
    eclipse下搭建shell脚本编辑器--安装开发shell的eclipse插件shelled
    如何进行shell脚本正确性测试
    robot framework
    loadrunner参数化数据分配方法
  • 原文地址:https://www.cnblogs.com/heqinghui/p/3195411.html
Copyright © 2011-2022 走看看