题意
二维平面,屏幕是 (0, 1)–(0, m) 的线段
有 n 行 m 列座位在屏幕前面,是坐标范围 1 ≤ x ≤ n, 1 ≤ y ≤ m 的整点
有 k 个座位已经有人,求出到屏幕的视线不被任何人挡住的座位数量
q 次询问,每次修改一个人的坐标后求出答
题解
对于 y = 1 或 y = m 的列,每个人只会挡住自己正右方的人。特殊处理
一下。
而对于 y = 2, 3, . . . , m − 1,每个人挡住的区域是 (0, 1) 和 (0, m) 到这个
点的两条射线之间的区域。两条射线的方向都是 x 坐标增大,y 坐标一个增
大一个减小。最后不合法的区域就是这些区域的并集。
整个区域实际上构成一个折线图。对于每个 y,会有一个分界线 t,在这
一列上,x ∈ [1, t) 的点是满足条件的,而 x ∈ [t, n] 的点会被挡住。
折线图由 2k 个线段构成。这 2k 条线段有比较明显的性质,就是延长线
都经过 (0, 1) 或 (0, m)。可以把它们分成两类。
那么实际上可以对于延长线经过这两个点的线段分别维护一下斜率。
首先对每个 y,如果这一列有多个人,那么肯定考虑 x 最小的人,因为
小的会完全覆盖大的。
然后对于 (0, 1) 和 (0, m) 分开考虑。
以 (0, 1) 为例,所有线段都是从某个点往右上方走。
如果按 y 从小到大加入线段,不难发现斜率大的线段一旦加入,就一直
会覆盖斜率小的线段。对于某个 y,要找到最小的合法 x,那么肯定取的是
前面所有线段中斜率最大的线段。所以对 y 正着扫一遍,在扫的同时维护一
下最大的斜率,即可得出每一列只考虑经过 (0, 1) 的线段的答案。
(0, m) 同理,倒着扫一遍维护斜率最小(绝对值最大)的线段即可。每
个 y 在两种情况取 min 就是答案。
#include
#include
#include
#include
#include
#include
#include
#include
#include