HDU-1394 Minimum Inversion Numbe…

HDU - 1394
题目大意:N 个数 , 从 0 至 N-1 。给定出事序列,标记为状态 1。
一种操作:将首元素放置到最后。
一共进行 N-1 次操作,每次操作形成一种新的状态。加上初始状态一共 N 个状态。
求 N 种状态中逆序数最小的一组的 逆序数。

(1)暴力过:
#include <iostream> 
#include <cstdio> 
#include <cstdlib> 
#define M 5010 
using namespace std ;  
int map [ M ];  
int n , ans , t ;  
int main () 
{ //freopen("in.txt","r",stdin); 
    while ( scanf ( "%d" ,& n )!= EOF
    { t = 0 , ans = 99999999 ;
      for ( int i = 1 ; i <= n ; i ++)  
         scanf ( "%d" ,& map [ i ]);  
      for ( int i = 1 ; i <= n ; i ++)  
        for ( int j = i + 1 ; j <= n ; j ++)  
          if ( map [ i ]> map [ j ]) t ++;  
      ans = t ;  
      for ( int i = 1 ; i <= n ; i ++)
      { t = t - map [ i ]+ n - map [ i ]- 1 ;  
        ans = min ( t , ans );    
      }  
      printf ( "%d\n" , ans ); 
    }  
    return 0
}

(2)线段树:
#include <iostream> 
#include <cstdio> 
#include<cstring> 
#define min(x,y) (x<y?x:y) 
#define Max 5005 
#define Inf 0x7fffffff 

using namespace std; 
int sum[Max<<2]; 
void build(int l,int r,int id
{   sum[id] = 0;
    if(l==r)    return; 
    int mid=(l+r)/2;
    build(l,mid,id*2); 
    build(mid+1,r,id*2+1); 
} 
void update(int x,int l,int r,int id
{  
   if(x==l&&l==r{
        sum[id]++;
        return;
    } 
   int mid=(l+r)/2; 
   if(x<=mid) 
      update(x,l,mid,id*2);
   else 
      update(x,mid+1,r,id*2+1); 
   sum[id]++; 
   return
} 
int query(int x,int l,int r,int id
{
    if(l==r)
        return 0; 
 int mid = (l+r)/2; 
 if(x<=mid)
    {
        return query(x,l,mid,id*2)+sum[id*2+1];
    } 
 else
    {
        return query(x,mid+1,r,id*2+1);
    } 
 return 0
} 
int x[Max]; 
int n; 
int main() 
{
    //freopen("in.txt","r",stdin); 
   int i,j; 
   while(scanf("%d",&n)!=EOF)
   {   build(1,n,1);
        int sums=0; 
       for(i=0;i<n;i++) 
       {   scanf("%d",&x[i]); 
           sums+=query(x[i],0,n-1,1); 
           update(x[i],0,n-1,1);
       } 
       int min=sums; 
       for(i=0;i<n-1;i++) 
       {   min+=n-x[i]*2-1; 
           sums=min(min,sums); 
       } 
       printf("%d\n",sums); 
   } 
 return 0;
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值