/****************************
用线段树求逆序数
对于a1,a2,....an 的逆序数sum
我们求a2,a3,....an,a1的逆序数时,
假设比a1小的数的个数为t,则比a1大的数为n-t-1;
那么sum=sum+n-2*t-1;
由于这题给出的数据是0~n-1的数,所以不需要离散化,比ai小的数的个数就是ai个
*****************************/
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.
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
#include<cstdio>
using namespace std;
const int maxn=5005;
int a[maxn<<2];
void build(int l, int r, int rt)
{
if(l==r)
{
a[rt]=0;
return;
}
int mid=(l+r)>>1;
build(l, mid, rt<<1);
build(mid+1, r, rt<<1|1);
a[rt]=0;
}
void PushUp(int rt)
{
a[rt]=a[rt<<1]+a[rt<<1|1];
}
void updata(int l, int r, int x, int rt)
{
if(l==r)
{
a[rt]++;
return;
}
int m=(l+r)>>1;
if(x<=m) updata(l, m, x, rt<<1);
else updata(m+1, r, x, rt<<1|1);
PushUp(rt);
}
int Query(int l, int r, int L, int R, int rt)
{
if(L<=l && r<=R)
{
return a[rt];
}
int m=(l+r)>>1;
int ans1=0, ans2=0;
if(L<=m) ans1+=Query(l, m, L, R, rt<<1);
if(R>m) ans2+=Query(m+1, r, L, R, rt<<1|1);
return ans1+ans2;
}
int main()
{
int n, i, sum;
int b[5005];
while(scanf("%d", &n)!=EOF)
{
sum=0;
build(0, n-1, 1);
for(i=0; i<n; i++)
{
scanf("%d", &b[i]);
sum+=Query(0, n-1, b[i], n-1, 1);
updata(0, n-1, b[i], 1);
}
int min=sum;
for(i=0; i<n; i++)
{
sum=sum+n-2*b[i]-1;
if(sum<min)
min = sum;
}
printf("%d\n", min);
}
return 0;
}