Insertion Sort

发布时间 2023-11-03 10:03:53作者: Zlc晨鑫

想象一下,冒泡排序交换的两个数一定是原数组的逆序对(反证容易证明:如果不是逆序对,相遇之后不会交换。两个数只有在相遇的时候才会使得下标相对大小互换,相遇之前一定是左的在左,右的在右。而不是逆序对的话,相遇的时候也不会交换,所以就一直不会交换)。

因为有序数组一定没有逆序对,所以逆序对一定换完了,所以swap次数就是逆序对总数。


我的写法是\(f_{i,j}\),表示\(k\in [j,n]\)\(a[k]<a[i]\)\(k\)的个数。

交换次数就是\(f_{1,2}+f_{2,3}+...\)。(通过此式可以发现,如果\(a[x]<a[y],x,y\),交换二者一定不优)

比如枚举交换的是\(x,y,x<y\),那么\(x\)之前和\(y\)之后的点的\(f_{k,k+1}\)都没有改变,对交换次数贡献不变。

对于\(x\)\(y\)\(f_{y,y+1} \rightarrow f_{y,x+1} + [a[x]<a[y]?]\)\(f_{x,x+1}\rightarrow f_{x,y+1}\)

如果通过上面的式子退出来逆序对才要交换,\([a[x]<a[y]]=0\)

现在关键是\([x+1,y-1]\)中的数的\(f_{k,k+1}\)又是如何变化的呢?

昨晚不知道怎么想的,用了权值树状数组查询一段值域的数的个数,其实完全不用。

\(a[k]>a[x]\),则\(f_{k,k+1}\leftarrow +1\)
\(a[k]>a[y]\),则\(f_{k,k+1}\leftarrow -1\)

也就是说,要知道\(k\in [x+1,y-1],a[k]>t\)的数的个数。

数据范围很小,再预处理一个\(g_{i,x}\),表示\(k \in [1,i],a[k]>x\)的数的个数不就行了?

那对答案的贡献不就是\(g_{y-1,a[x]}-g_{x,a[x]}-g_{y-1,a[y]}+g_{x,a[y]}\)吗?

昨晚把上面的式子合并了,写成了\(a[y]<a[k]<a[x]\),要\(-1\),其实也可以写成\(a[k]<a[x]\),减去\(a[k]<a[y]\)的。

然后再套一层前缀和预处理,就出来了。