逆序数———线段树/树状数组

http://acm.hdu.edu.cn/showproblem.php?pid=1394

方法一:

线段树

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream> 
using namespace std;
int s[5000*4+1];
int aa[5001];
int query(int l,int r,int L,int R,int cr){
    if(l==L&&r==R){
        return s[cr];
    }
    int mid=(L+R)/2;
    int ans=0;
    if(l<=mid){
        ans+=query(l,min(mid,r),L,mid,cr*2); 
    }
    if(r>mid){
        ans+=query(max(mid+1,l),r,mid+1,R,cr*2+1);
    }
    return ans;
}
void update(int p,int L,int R,int cr){
    if(p==L&&p==R){
        s[cr]++;
        return ;
    }
    int mid=(L+R)/2;
    
    if(p<=mid){
        update(p,L,mid,cr*2);
    } 
    else{
        update(p,mid+1,R,cr*2+1);
    }
    s[cr]=s[cr*2]+s[cr*2+1];
} 
int main(){
    int n;
    while( EOF!=scanf("%d",&n) ){
        memset(s,0,sizeof(s));
        int sum=0;
        for(int i=0;i<n;i++){
            scanf("%d",&aa[i]);
            sum+=query(aa[i]+1,n-1,0,n-1,1);
            update(aa[i],0,n-1,1);
        }
        int mins=sum;
        
        for(int i=0;i<n;i++){
            sum=sum+n-1-2*aa[i];
                mins=min(sum,mins);
        }
        printf("%d\n",mins);    
    }
        
}

  

posted @ 2018-07-31 19:51  bear_ge  阅读(126)  评论(0编辑  收藏  举报