1394.Minimum Inversion Number(HDU)

题意理解

给定一个长度N的全排列,对这样的一个序列对应一个逆序数;现在每次将第一个数放到序列最后一位,形成一个新的序列,这个新序列也对应一个逆序数。求所有这些放法对应逆序数的最小值。逆序数定义:对于i<j,a[i]>a[j]。

问题分析

用树状数组数据结构

转一:问题分两层解决,一是求单个序列的逆序数,而是求n个序列逆序数的最小值

转二:求单个序列的逆序数。就是把序列每个数的逆序数加起来,对于单个数的逆序数,理解为这个数前面从第一位开始到它自己,有几个数比它大,有几个算几个逆序数。再进一步理解,计算它前面有几个数比它大,可以转化为前面数的总数量减去前面比它小的数的个数。总数量就是这个数所在的序号减1,前面比它小的数的个数计算方法是每遍历序列中一个数,就做一个标记为1,表示数已经存在,数一下这些标记的数量就是比它小的数的个数。这是一个前缀和。复杂度O(nlogn)

转三:求n个序列逆序数的最小值。常见思路是一次遍历序列,总复杂度O(n^2logn)。前后两个序列变化点在于,第一个数放到最后一位。从这个角度出发,影响分为三方面,这个数本身的逆序数,这个数前面的逆序数和,这个数后面的逆序数和。第一个数所在位置后面的数没有影响,因为这个数都小于后面的数,不构成逆序对;而第一个数所在位置的前面的每个数都会少一个逆序数,因为比它小的数都少了一个比它大的数;这个数本身的逆序数变大了,从0到n-1-a[i],所有比它的数都构成了逆序对。算法复杂度为O(nlogn+n)=O(nlogn).

参考:https://blog.csdn.net/ssimple_y/article/details/53744096

其他

这题思路巧,没思路,问了同学才理解,自己很难想到。

直接求不行,转化为差值

直接求不行,用变化值分析逐步来求解

灵活用数组下标,一次遍历记录已经处理的信息,善于利用这些信息求目标解。

代码链接

https://github.com/xierensong/learngit/blob/master/hdu/h1394.cpp

猜你喜欢

转载自blog.csdn.net/xiexie1357/article/details/82379683