【hdu1394】Minimum Inversion Number

时间:2022-07-23 04:41:28
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”的存在,被坑了好几次。
 #include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#define MAXN 100000
using namespace std;
int segtree[MAXN*],a[MAXN*];
int n,sum;
void adddata(int now)
{
segtree[now]=segtree[(now<<)]+segtree[(now<<)+];
}
void buildtree(int now,int l,int r)
{
segtree[now]=;
if (l==r) return;
int mid=(l+r)>>;
buildtree((now<<),l,mid);
buildtree((now<<)+,mid+,r);
adddata(now);
}
int query(int now,int l,int r,int begin,int end)
{
if (begin<=l && end>=r) return segtree[now];
int mid=(l+r)>>,ans=;
if (begin<=mid) ans+=query((now<<),l,mid,begin,end);
if (end>mid) ans+=query((now<<)+,mid+,r,begin,end);
return ans;
}
void pointchange(int now,int l,int r,int x,int v)
{
if (l==r) {segtree[now]+=v; return;}
int mid=(l+r)>>;
if (x<=mid) pointchange((now<<),l,mid,x,v);
else pointchange((now<<)+,mid+,r,x,v);
adddata(now);
}
int main()
{
int i;
int minn;
while (~scanf("%d",&n))
{
buildtree(,,n-);
sum=;
for (i=;i<n;i++)
{
scanf("%d",&a[i]);
sum+=query(,,n-,a[i],n- );
pointchange(,,n-,a[i],);
}
minn=sum;
for (i=;i<n;i++)
{
sum+=n-*a[i]-;
minn=min(minn,sum);
}
printf("%d\n",minn);
}
return ;
}