Atcoder Regular Contest 092 A 的改编
题目大意
给定平面上的 \(n\) 个点 \(p_1, \dots, p_n\) 。第 \(i\) 点的坐标为 \((x_i, y_i)\) 。\(x_i\) 各不相同,\(y_i\) 也各不相同。若两点 \(p_i\) 和 \(p_j\) 满足 \(x_i < x_j\) 且 \(y_i < y_j\) 则可配成一对。求这 \(n\) 个点之中最多可配成多少对。(注:每个点最多出现在一个点对中)
解法
按 \(y\) 坐标从大到小考虑。\(y\) 值最大的点,不妨记为 \((x_i, y_i)\), 与 \(x\) 坐标小于 \(x_i\) 且 \(y\) 坐标小于 \(y_i\) 的点中 \(y\) 坐标最大的点配对。若此循环。
实现
怎么实现比较简洁呢?
不要总想着模拟,多想想要求的量是什么?什么东西是不必计算的?
想了一下,没挖掘出进一步的规律,所以 end up with 模拟,sigh。。
一个模拟算法:
将 \(n\) 个点按 \(x\) 坐标从小到大排序。用 std::map<int,int>
保存每个 \(y\) 坐标值(所属的点)在排序后的序列中位置。
用树状数组支持查询“前 \(i\) 个 \(y\) 坐标值中的最大值”,用掉的点的 \(y\) 坐标替换为 \(-\infty\) 。
还是觉得这个做法太蠢了,一点都不优雅。
EDIT 1
这样改编貌似没啥新意。先考虑一维的情况(一维是平凡情形)就不难想到二维的解法。那么三维、四维怎么做呢?