逆序数———线段树/树状数组
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); } }