如果只能交换相邻两项,那么答案就是排列的逆序对数。
现在我们就是要求交换两个数,使得交换后的排列逆序对数最少。
不难发现我们一定不会交换满足 /(i<j,h_i<h_j/) 的 /((i,j)/),因为这样只会让逆序对变多。
考虑怎么刻画减少的逆序对:
- /((i,j)/);
- 满足 /(i<k<j,h_k<h_i/) 的 /((i,k)/);
- 满足 /(i<k<j,h_k>h_j/) 的 /((k,j)/)。
如果我们把每一个位置看出一个二维平面上的点 /((i,h_i)/),那么后两类减少的逆序对就可以很好地被刻画为 $2/times $ 以 /((i,h_i)/) 为左上角、/((j,h_j)/) 为右下角的矩形内部(不算边界)的点的数量。
所以我们就要找到一个包含点数最多的矩形。
容易想到被另一个矩形包含的矩形一定不优,也就是说我们的左上角只会选择满足 /(h_i=/max/limits_{a=1}^i h_a/) 的 /((i,h_i)/)(设所有满足该条件的点组成的集合为 /(L/))、右下角只会选择满足 /(h_j=/min/limits_{b=j}^n h_b/) 的 /((j,h_j)/)(设所有满足该条件的点组成的集合为 /(R/)),这个可以 /(O(n)/) 直接求出。
发现这样似乎还是不太好做,考虑换一种想法:求覆盖一个点的点数最多的矩形。
由于 /(L/) 和 /(R/) 中的 /(h/) 随着 /(i/) 的增大而增大,那么对于一个点 /((k,h_k)/),我们可以二分找到 /(L/) 集合中第一个纵坐标 /(>h_k/) 的点 /((l,h_l)/) 和 /(R/) 集合中最后一个纵坐标 /(<h_k/) 的点 /((r,h_r)/),则所有左上角的横坐标在 /([l,k-1]/) 区间内、右下角的横坐标在 /([k+1,r]/) 区间内的矩形都会覆盖这个点。
那么就可以转化成二维数点问题,扫描线即可。
代码:https://paste.ubuntu.com/p/Wz6g4Rvxzq/。
原创文章,作者:jamestackk,如若转载,请注明出处:https://blog.ytso.com/277364.html