• HDU-1394 Minimum Inversion Number(线段树求逆序数)


    Minimum Inversion Number

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 15675 Accepted Submission(s): 9569

    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

    这道题目有两个地方可以留意一下。
    首先求一个数列的逆序数
    首先将这个数列排序,然后从最后一个数,边询问边更新
    第二,根据题意,将第一个数放到最后一个,形成的新数列应该怎么求逆序数。其实可以递推,和没有变化前的数列比较逆序数增加了(n-1-a[i])-a[i]

    #include <iostream>
    #include <string.h>
    #include <stdlib.h>
    #include <algorithm>
    #include <math.h>
    
    using namespace std;
    #define MAX 5000
    int segTree[MAX*4+5];
    int n;
    int a[MAX];
    int b[MAX];
    int c[MAX];
    void PushUp(int node)
    {
        segTree[node]=segTree[node<<1]+segTree[node<<1|1];
    }
    void build(int node,int begin,int end)
    {
        if(begin==end)
        {
            segTree[node]=0;
            return;
        }
        int m=(begin+end)>>1;
        build(node<<1,begin,m);
        build(node<<1|1,m+1,end);
        PushUp(node);
    }
    void Update(int node,int begin,int end,int ind,int num)
    {
        if(begin==end)
        {
            segTree[node]+=num;
            return;
        }
        int m=(begin+end)>>1;
        if(ind<=m)
            Update(node<<1,begin,m,ind,num);
        else
            Update(node<<1|1,m+1,end,ind,num);
        PushUp(node);
    }
    int Query(int node,int begin,int end,int left,int right)
    {
        if(left<=begin&&end<=right)
            return segTree[node];
        int ret;
        int m=(begin+end)>>1;
        ret=0;
        if(left<=m)
            ret+=Query(node<<1,begin,m,left,right);
        if(right>m)
            ret+=Query(node<<1|1,m+1,end,left,right);
        return ret;
    }
    int cmp(int x,int y)
    {
        return x<y;
    }
    int main()
    {
        int sum;
        while(scanf("%d",&n)!=EOF)
        {
            sum=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                c[i]=a[i];
                b[a[i]]=i;
            }
            build(1,1,n);
            sort(a+1,a+n+1,cmp);
            for(int i=n;i>=1;i--)
            {
                sum+=Query(1,1,n,1,b[a[i]]);
                Update(1,1,n,b[a[i]],1);
            }
            int num;
            num=sum;
            int ans;
            ans=sum;
            for(int i=1;i<n;i++)
            {
                num+=-c[i]+(n-1-c[i]);
                if(ans>num)
                    ans=num;
            }
            printf("%d
    ",ans);
    
    
        }
        return 0;
  • 相关阅读:
    使用jQuery简单实现产品展示的图片左右滚动功能
    分布式缓存 memcache学习
    js打印html中的内容
    lucene 搜索引擎使用案例
    jQuery 知识点积累
    Oracle 11g 卸载
    #region 自适应屏幕分辨率
    C#泛类型链表的实现
    C#可以获取Excel文件中Sheet的名字
    关于 List<T>
  • 原文地址:https://www.cnblogs.com/dacc123/p/8228835.html
Copyright © 2020-2023  润新知