【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.
原文地址:https://www.cnblogs.com/DMoon/p/5096650.html