• hdu 1394 Minimum 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. 

    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..n,2..n..1,3..n..12,4..n..1..3,...这n种排列最小的逆序数。

    1、树状数组

    写这道题更多地是给自己一个树状数组的模板。建立在sum数组上的lowbit,add,getsum三个操作。

    2、求逆序数

    在初始全为0的长为n的数组上的操作。结构体排序。若有重复的值,注意排序的比较方式,应当是序号较大的排在后面,避免被记入逆序数。

    3、本题技巧

    0..n-1这n个数的序列。若第一个数为a,将其放至最后一位,则逆序数减少a,增加n-1-a,从而看做增加n-1-2a。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    const int maxn=5000;
    const int inf=1000000000;
    
    int a[maxn+10];
    
    struct tnode
    {
        int num;
        int seq;
        bool operator<(const tnode& y) const
        {
            return num<y.num;
        }
    };
    tnode node[maxn+10];
    
    int sum[maxn+10];
    
    inline int lowbit(int x)
    {
        return x&-x;
    }
    
    inline void add(int x,int val,int n)//向1..n序列的x位置加上val
    {
        for(int i=x;i<=n;i+=lowbit(i))
            sum[i]+=val;
    }
    
    inline int getsum(int x)//1..x的和
    {
        int ret=0;
        for(int i=x;i;i-=lowbit(i))
            ret+=sum[i];
        return ret;
    }
    
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            for(int i=1;i<=n;i++)
                scanf("%d",a+i);
            for(int i=1;i<=n;i++)
                node[i]=(tnode){a[i],i};
            sort(node+1,node+n+1);
            int ans0=0;
            memset(sum,0,sizeof(sum));
            for(int i=n;i>=1;i--)
            {
                ans0+=getsum(node[i].seq);
                add(node[i].seq,1,n);
            }
            int ans=ans0;
            for(int i=1;i<n;i++)
            {
                ans0=ans0+n-1-2*a[i];//0..n-1的排列逆序数规律
                ans=min(ans,ans0);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    黑客技术训练场
    常用安全测试用例
    Burp suite 一款Web渗透测试的集成套件
    soapUI安全测试教程
    黑客视频动画
    Cookie安全测试
    安全测试资源列表【持续收集中】
    软件安全测试系列视频
    软件安全测试辅助工具列表【持续收集中】
    WEB安全问题的层次
  • 原文地址:https://www.cnblogs.com/acboyty/p/9745807.html
Copyright © 2020-2023  润新知