题解:AT_iroha2019_day4_l ...好きです
在我的博客中查看
先考虑静态问题。先把绝对值拆开,只考虑询问左边的点,反过来的情况类似。容易想到在平面直角坐标系上考虑。考虑每个点对答案的贡献。对于点
于是问题就变成了:
平面上有若干条直线,多次给定
x_{0} ,求出直线上的点中,横坐标为x_{0} 的点中纵坐标为正数且最小的。
把操作和询问的
注意到上凸包有以下性质:
- 随着
x 坐标的增大,使得y 最小的直线斜率单调递减。
所以我们考虑维护一个单调栈,从栈底到栈顶从小到大存放直线的斜率,并且保证栈中每一条直线都存在某个位置,使得这堆直线中的最小值在此直线取到(也就是说保证每条直线都是凸包的一部分)。
加入一条新直线
-
 如图,$l$ 是新加入的直线。由于 $l$ 的斜率小于 $l'$ 的斜率,所以对于 $P$ 点右侧的询问,$l$ 的纵坐标一定小于 $l'$ 的纵坐标,因此 $l'$ 被弹出。但直线 $m$ 被保留了。 -
 如图,虽然 $l$ 的斜率大于栈顶 $l'$ 的斜率,但是由于 $l$ 和 $l'$ 的交点 $Q$ 在 $l'$ 与 $m$ 的交点 $S$ 左侧,所以对于 $P$ 右侧的询问,纵坐标最小值不可能在 $l'$ 取到,这种情况我们也需要弹栈。
以上就讨论完了加入直线的情况。下面考虑如何处理询问。根据凸包的性质,随着
现在静态问题就解决了,时间复杂度为
对时间轴建立线段树。还是把操作和询问按
代码实现非常清晰:Code
下面附上我写的 generator 供大家调试,可以自行修改数据范围。为了方便,使用了 vector.erase() 用来完成从 set 中随机选取元素的过程,时间复杂度比较劣,但实测生成大数据也很快。(实际上更好的做法是把删除的元素和 vector.back() 交换,然后 pop_back()。)
(在文首链接查看)