本题就是求逆序对,因为数据范围比较小,可以不用离散化,直接用权值线段树就可以了
权值线段树就是在线段树里记录每个数出现的次数,而不是记录位置+值,
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5000+10;
int num[maxn << 2 + 10];
int a[maxn];
void push_up(int i)
{
num[i]=num[i<<1] + num[i<<1|1];
}
void build(int l , int r , int i)
{
num[i] = 0;
if(l == r){return;}
int mid = (l+r) >>1 ;
build(l,mid,i<<1);
build(mid+1,r,i<<1|1);
}
int query(int L , int R , int l , int r , int i)
{
// cout << L << " --- " << R << endl;
if(L >= l&& R <= r)
{
return num[i];
}
int mid = (L + R) >> 1;
if(mid >= r)
{
return query(L , mid , l,r,i << 1 );
}
else if(mid < l)
{
return query(mid + 1 , R , l,r,i << 1 | 1);
}
else
{
return query(L , mid , l,r,i << 1 ) + query(mid + 1 , R , l,r,i << 1 | 1);
}
}
void update(int L , int R , int i , int x)
{
if(L == x && L == R)
{
num[i]++;
return ;
}
int mid = (L + R) >> 1;
if(mid >= x)
{
update(L , mid , i << 1 , x);
}
else if(mid < x)
{
update(mid + 1 ,R, i << 1 | 1 , x);
}
push_up(i);
}
int main()
{
int n;
while(cin>>n)
{
build(1,n,1);
int ans=0,x;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
a[i]++;
ans+=(query(1,n,a[i],n,1) - query(1,n,a[i],a[i],1));
// cout << " 0---0" <<endl;
update(1,n,1,a[i]);
}
int sum=ans;
// cout << sum << " --" << endl;
for(int i=n-1;i>=0;i--)
{
ans=ans-(n-a[i])+(a[i]-1);
sum=min(sum,ans);
}
cout<<sum<<endl;
}
return 0;
}