hdu 1394 Minimum Inversion Number

权值线段树求逆序对,题目依次把首数字移向尾部问最小逆序对。移动的时候查询更新一下就好。

#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;
}
View Code

猜你喜欢

转载自www.cnblogs.com/LMissher/p/9558404.html