hdu 1394

/*题意描述: 求逆序对
给你一个有0--n-1数字组成的序列,然后进行这样的操作,
每次将最前面一个元素放到最后面去会得到一个序列,那么这样就形成了n个序列,
那么每个序列都有一个逆序数,找出其中最小的一个输出!

*/

#include<stdio.h>

const int maxn=5005;

struct  Node
{
    int left,right,sum;     
}Tree[3*maxn];
int a[maxn];
void build(int left,int right,int pos)
{
     Tree[pos].left=left;
     Tree[pos].right=right;
     
     if(left==right)
     {
        Tree[pos].sum=0;
        return ;
     }   
     int mid=(left + right)>>1;
     build(left,mid,2*pos);
     build(mid+1,right,2*pos+1);
     Tree[pos].sum=Tree[2*pos].sum+Tree[2*pos+1].sum;
}


int query(int left,int right,int pos)
{
       if(Tree[pos].left==left && Tree[pos].right==right)
       {
            return Tree[pos].sum;             
       }
       
       int mid=(Tree[pos].left + Tree[pos].right)>>1;
       
       if(right<=mid)
         return query(left,right,2*pos);
       else if(left>mid)
         return query(left,right,2*pos+1);
       else
       {
         return query(left,mid,2*pos) + query(mid+1,right,2*pos+1);
       }
     //return Tree[pos].sum=(Tree[2*pos].sum+Tree[2*pos+1].sum);
}
/*
void update(int left,int right,int pos)
{
   
   if(left==Tree[pos].left && Tree[pos].right==right)   
   {
     Tree[pos].sum++;  
   }  
   
   int mid=(Tree[pos].left + Tree[pos].right)>>1;
    
   if(right<=mid)
   {
      update(left,right,2*pos);              
   }
   else if(left>mid)
   {
      update(left,right,2*pos+1);     
   }
   else 
   {
        update(left,mid,2*pos);
        update(mid+1,right,2*pos+1);
   }
    Tree[pos].sum=Tree[2*pos].sum+Tree[2*pos+1].sum;
}*/

void update(int id,int pos)
{
     Tree[pos].sum++;
     if(Tree[pos].left==Tree[pos].right)
     {
      return ;                                 
     }
     
     int mid= (Tree[pos].left+ Tree[pos].right)>>1;
     
     if(id<=mid)
       update(id,2*pos);
     else
      update(id,2*pos+1);
}


int main()
{
    int n,i;
    while(scanf("%d",&n)!=EOF)
    { 
      build(1,n,1); 
      
      int count=0;
    //  printf("*\n");
      
      for(i=1;i<=n;i++)
      {
        scanf("%d",&a[i]);
        int x=query(a[i]+1,n,1);
        count+=x;
        printf("%d ",x);
        update(a[i],1);
      } 
      
     // printf("(count)%d\n",count);
        int ans=count;  
        for(i=1;i<=n;i++){  
            count+=-a[i]+n-1-a[i];  
        //    printf("%d\n",count);  
            if(ans>count)ans=count;  
        }  
                                 
        printf("%d\n",ans);                     
}    
return 0;    
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值