Java教程

LOJ#535「LibreOJ Round #6」花火 题解

本文主要是介绍LOJ#535「LibreOJ Round #6」花火 题解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

题面

如果只能交换相邻两项,那么答案就是排列的逆序对数。

现在我们就是要求交换两个数,使得交换后的排列逆序对数最少。

不难发现我们一定不会交换满足 \(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/。

这篇关于LOJ#535「LibreOJ Round #6」花火 题解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!