zoukankan      html  css  js  c++  java
  • 【hdu1394】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
     
    Author
    CHEN, Gaoli
     
    Source
    题目大意:求逆序对数目,然后将第一个数字置于队尾在求一遍,直到每个数字都到过队尾的最小逆序对数.
    思路:用线段树维护,每次插入统计在其右边的逆序对数和,再用公式推导出每次变换的逆序对数。
    attention:注意“0”的存在,被坑了好几次。
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <cstring>
     5 #define MAXN 100000
     6 using namespace std;
     7 int segtree[MAXN*4],a[MAXN*4];
     8 int n,sum;
     9 void adddata(int now)
    10 {
    11     segtree[now]=segtree[(now<<1)]+segtree[(now<<1)+1];
    12 }
    13 void buildtree(int now,int l,int r)
    14 {
    15     segtree[now]=0;
    16     if (l==r)    return;
    17     int mid=(l+r)>>1;
    18     buildtree((now<<1),l,mid);
    19     buildtree((now<<1)+1,mid+1,r);
    20     adddata(now);
    21 }
    22 int query(int now,int l,int r,int begin,int end)
    23 {
    24     if (begin<=l && end>=r)    return segtree[now];
    25     int mid=(l+r)>>1,ans=0;
    26     if (begin<=mid)    ans+=query((now<<1),l,mid,begin,end);
    27     if (end>mid)    ans+=query((now<<1)+1,mid+1,r,begin,end);
    28     return ans;
    29 }
    30 void pointchange(int now,int l,int r,int x,int v)
    31 {
    32     if (l==r)    {segtree[now]+=v;    return;}
    33     int mid=(l+r)>>1;
    34     if (x<=mid)    pointchange((now<<1),l,mid,x,v);
    35     else    pointchange((now<<1)+1,mid+1,r,x,v);
    36     adddata(now);
    37 }
    38 int main()
    39 {
    40     int i;
    41     int minn;
    42     while (~scanf("%d",&n))
    43     {
    44         buildtree(1,0,n-1);
    45         sum=0;
    46         for (i=0;i<n;i++)
    47         {
    48             scanf("%d",&a[i]);
    49             sum+=query(1,0,n-1,a[i],n-1 );
    50             pointchange(1,0,n-1,a[i],1);
    51         }
    52         minn=sum;
    53         for (i=0;i<n;i++)
    54         {
    55             sum+=n-2*a[i]-1;
    56             minn=min(minn,sum);
    57         }
    58         printf("%d
    ",minn);
    59     }
    60     return 0;
    61 }
     
    —Anime Otaku Save The World.
  • 相关阅读:
    待你长发及腰
    《线段树》讲稿
    Codeforces #Round 376 F 题解
    包裹快递 题解
    Codeforces #Round 376 部分题解
    圆圈舞蹈 题解
    奶牛晒衣服 题解
    BZOJ 1034 题解
    BZOJ 1045 题解
    BZOJ 1054 题解
  • 原文地址:https://www.cnblogs.com/DMoon/p/5096650.html
Copyright © 2011-2022 走看看