#include <stdio.h>
#include <string.h>
#define maxn 5000
struct node{
int l,r,w;
}e[maxn*4];
void build(int a,int b,int c)
{
e[c].l=a;
e[c].r=b;
e[c].w=0;
if(a==b)
return;
int mid=(a+b)/2;
build(a,mid,2*c);
build(mid+1,b,2*c+1);
}
void update(int a,int b,int c,int val)
{
if(e[c].l==a&&e[c].r==b)
{
e[c].w+=val;
return;
}
int mid=(e[c].l+e[c].r)/2;
if(b<=mid)
update(a,b,2*c,val);
else if(a>mid)
update(a,b,2*c+1,val);
else
{
update(a,mid,2*c,val);
update(mid+1,b,2*c+1,val);
}
e[c].w=e[2*c].w+e[2*c+1].w;
}
int query(int a,int b,int c)
{
if(e[c].l==a&&e[c].r==b)
return e[c].w;
int mid=(e[c].l+e[c].r)/2;
if(b<=mid)
return query(a,b,2*c);
else if(a>mid)
return query(a,b,2*c+1);
else
return query(a,mid,2*c)+query(mid+1,b,2*c+1);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int i,j,k,sum,d[maxn];
build(0,n-1,1);
sum=0;
for(i=0;i<n;i++)
{
scanf("%d",&d[i]);
sum+=query(d[i],n-1,1);
update(d[i],d[i],1,1);
}
int ans=sum;
for(i=0;i<n;i++)//每次将第一位数移到最后一位时,逆序数变化为增加了比他大的个数n-d[i]-1
//,减小比他小的个数d[i],求出移动0到n-1次中逆序数最小的那个
{
sum=sum+(n-d[i]-1)-d[i];
ans=sum<ans?sum:ans;
}
printf("%d\n",ans);
}
return 0;
}
线段树求逆序数就是讲输入的数组依次插入线段树,线段树的段值w表示该段中以插入的数字个数,每次插入,计算已插入的比插入数大的数的个数,总和就是逆序数