hdu 1394
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394
思路:求最小的逆序数。。。可以暴力,也可以用线段树来做。。。下面是用线段树实现的代码:
View Code
1 #include<iostream> 2 const int MAXN=5007; 3 using namespace std; 4 int sum[MAXN<<2]; 5 int x[MAXN]; 6 7 //更新父结点信息 8 void Push_Up(int rt){ 9 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 10 } 11 12 void Build(int l,int r,int rt){ 13 sum[rt]=0; 14 if(l==r)return ; 15 int m=(l+r)/2; 16 Build(l,m,rt<<1); 17 Build(m+1,r,rt<<1|1); 18 } 19 20 //单点更新 21 void Updata(int p,int l,int r,int rt){ 22 if(l==r){ 23 sum[rt]++; 24 return ; 25 } 26 int m=(l+r)>>1; 27 if(p<=m)Updata(p,l,m,rt<<1); 28 else Updata(p,m+1,r,rt<<1|1); 29 Push_Up(rt); 30 } 31 32 int query(int L,int R,int l,int r,int rt){ 33 if(L<=l&&r<=R){ 34 return sum[rt]; 35 } 36 int m=(r+l)>>1; 37 int ret=0; 38 if(L<=m)ret+=query(L,R,l,m,rt<<1); 39 if(R>m)ret+=query(L,R,m+1,r,rt<<1|1); 40 return ret; 41 } 42 43 44 int main(){ 45 int n; 46 while(~scanf("%d",&n)){ 47 Build(0,n-1,1); 48 int s=0; 49 for(int i=0;i<n;i++){ 50 scanf("%d",&x[i]); 51 s+=query(x[i],n-1,0,n-1,1); 52 Updata(x[i],0,n-1,1); 53 } 54 int ret=s; 55 for(int i=0;i<n;i++){ 56 s+=n-x[i]-1-x[i]; 57 ret=min(ret,s); 58 } 59 printf("%d\n",ret); 60 } 61 return 0; 62 }