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;
    }
  • 相关阅读:
    【郑轻邀请赛 G】密室逃脱
    【郑轻邀请赛 C】DOBRI
    【郑轻邀请赛 F】 Tmk吃汤饭
    【郑轻邀请赛 I】这里是天堂!
    【郑轻邀请赛 B】base64解密
    【郑轻邀请赛 A】tmk射气球
    【郑轻邀请赛 H】 维克兹的进制转换
    解决adb command not found以及sdk环境配置
    adb shell 命令详解,android, adb logcat
    Unexpected exception 'Cannot run program ... error=2, No such file or directory' ... adb'
  • 原文地址:https://www.cnblogs.com/heqinghui/p/3195411.html
Copyright © 2011-2022 走看看