zoukankan      html  css  js  c++  java
  • HDU1394:Minimum Inversion Number

    Description

    The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj. 

    For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following: 

    a1, a2, ..., an-1, an (where m = 0 - the initial seqence) 
    a2, a3, ..., an, a1 (where m = 1) 
    a3, a4, ..., an, a1, a2 (where m = 2) 
    ... 
    an, a1, a2, ..., an-1 (where m = n-1) 

    You are asked to write a program to find the minimum inversion number out of the above sequences. 

    Input

    The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1. 

    Output

    For each case, output the minimum inversion number on a single line. 

    Sample Input

    10
    1 3 6 9 0 8 5 7 4 2

    Sample Output

    16

    题目大意:给你一个序列,每次将这个序列的最后一个元素移到第一位,问这些过程中,所生成的每种序列,最小的逆序对数为多少,输出这个最小逆序对数。
    解题思路:先用树状数组求出原始序列的逆序对数,然后开始把最后一位a[n]移到第一位,逆序对增加a[i]-1,逆序对减少n-a[i](这道题给出序列元素值的范围是0~n-1),然后每次移动更新ans就行。
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    using namespace std;
    int n; 
    int a[500001];//初始数组 
    int c[500001];
    int lowbit(int x)
    {
    	return x&-x;
    }
    void add(int x)
    {
    	while(x<=n)
    	{
    		c[x]+=1;
        	x+=lowbit(x);
    	}
    }
    int sum(int x)
    {
    	int s=0;
    	while(x>0)
    	{
    		s+=c[x];
    		x-=lowbit(x);
    	}
    	return s;
     } 
    int main()
    {
    	while(scanf("%d",&n)!=EOF)
    	{ 
    	    int ans=0;
    		memset(c,0,sizeof(c));
    	  for(int i=1;i<=n;i++)
    	  {
    	  	scanf("%d",&a[i] );
    	     	a[i]+=1; //树状数组不能出现0  否则在上面void add()中x+=lowbit(x)一直是0  会陷入死循环 
    		  	add(a[i]);
    		 	ans+=(i-sum(a[i]));//i为当前插入的个数  sum(a[i])为当前比它小的个数 
    	  }
    	   int  minn=50000000;
    	  for(int i=n;i>0;i--)
    	  {
    	  	minn=min(minn,ans+a[i]-1-(n-a[i] ));//把一个数从末尾移除 则前面比它大的元素(一共有n-a[i]个)的逆序列数都减一   把该数放到首位后它本来是没有逆序列 现在比他小的(一共a[i]-1个)都能和他构成一个逆序列  
    	  	ans=ans+a[i]-1-(n-a[i]);
    	  }
    	  printf("%d
    ",minn);
    	}
    	return 0;
    }
    
    
    
    

  • 相关阅读:
    eclipse 使用 maven 无法编译 jsp 文件的问题
    iOS开发-Quartz2D绘制时定时器选择
    iOSUI-事件处理
    iOS开发-数据存储
    iOSUI-UIScrollView属性,方法大全
    iOSUI-UITableView属性,方法大全
    iOS网络-NSURLSession/AFNetworking发送HTTPS网络请求
    iOS网络-AFNetworking检测网络状态
    iOS网络-AFNetworking序列化
    iOS网络-AFNetworking基本使用,文件下载,上传
  • 原文地址:https://www.cnblogs.com/kingjordan/p/12027044.html
Copyright © 2011-2022 走看看