权值线段树求逆序对,题目依次把首数字移向尾部问最小逆序对。移动的时候查询更新一下就好。
#include <bits/stdc++.h> #define Lson l,mid,rt<<1 #define Rson mid+1,r,rt<<1|1 using namespace std; const int M = 1e5+7; int n,a[5007],pos; int sum[M<<2]; void Pushup(int rt,int l,int r){ sum[rt]=sum[l]+sum[r]; } void build(int l,int r,int rt){ sum[rt]=0; if(l==r){ return ; } int mid=(l+r)>>1; build(Lson); build(Rson); Pushup(rt,rt<<1,rt<<1|1); } void update(int l,int r,int rt){ if(l==r){ sum[rt]++; return ; } int mid=(l+r)>>1; if(pos<=mid) update(Lson); else update(Rson); Pushup(rt,rt<<1,rt<<1|1); } int query(int L,int R,int l,int r,int rt){ if(L<=l&&r<=R){ return sum[rt]; } int mid=(l+r)>>1,res=0; if(L<=mid) res+=query(L,R,Lson); if(R>mid) res+=query(L,R,Rson); return res; } int main(){ while(~scanf("%d",&n)){ build(0,100000,1); int ans=0,res; for(int i=1;i<=n;i++){ scanf("%d",&a[i]);pos=a[i]; ans+=query(a[i]+1,100000,0,100000,1); update(0,100000,1); //cout<<ans<<endl; } res=ans; for(int i=1;i<=n;i++){ res+=(query(a[i]+1,100000,0,100000,1)-(a[i]==0?0:query(0,a[i]-1,0,100000,1))); ans=min(ans,res); //cout<<ans<<endl; } printf("%d\n",ans); } return 0; }