要找逆序对的算法,网上都是归并。可是我真的背不下来!
在http://blog.sina.com.cn/s/blog_4afd4f7c0100053j.html上看到的一篇文章。
找到了一种更好记的逆序对算法。(我相对自己而言,说实话,我是还没有写过一遍归并的人,二叉排序数没有总有个十几编了。)
再简述以下算法。
c[i]记录的是在i之前,1~i-1之间的比i元素要大的元素的个数。
比如
____________
|1 | 2 | 3 | 4 | 5|
|3 | 1 | 4 | 5 | 2|
c[1]=0;
c[2]=1;
c[3]=0;
c[4]=0;
c[5]=3;
可以发现,也不难证明,∑(c[i],i∈[2,n])就是逆序对的个数。
可以通过动态的维护一棵二叉排序数,使其效率达到NlogN的效率。
每次从树顶加入一个元素P,如果P>=Tree[i],说明i的左子树全部比P小,然后进入下一层比较。
如果有P<Tree[i],则说明,有Tree[i]本身及Tree[i]的右子树所有元素都比P要大,对于Tree,另开一个数组S[i]记录树节点i,包含其自身及右子树的总节点数。
通过过程中S的累加,就可以得到c数组的每一个值,每次纵深一棵树,平均效率LogN,N个元素,所以有NlogN的效率。
这个算法还有一个很好的用处,在上面所说的博文里面有介绍。
比如说三元逆序对。
三元逆序对,可以通过再一个数组c2,c2(i)=∑c(j)(j∈[2,n-1],A[j]>A[i]),于是就好了,至于k元逆序对,同理。
TYVJ 1744 中也可以用。不过还要有另外的处理。