[JOISC 2020] 掃除
[JOISC 2020] 掃除
平面上有一个腰长为 \(N\) 的直角三角形,三个顶点分别为 \((0, N), (0, 0), (N, 0)\),初始有 \(m\) 个点 \((x_i, y_i)\),编号依次为 \(1,2,\dots, m\),接下来是 \(q\) 次操作:
- 查询编号为 \(i\) 的点的坐标。
- 进行过程 H:给定 \(L\),想象端点为 \((0, 0), (0, L)\) 的线段竖直扫到 \((N-L, 0), (N-L, L)\),并把途径的所有点全部推到 \(x = N-L\)。
- 进行过程 V:给定 \(L\),想象端点为 \((0, 0), (L, 0)\) 的线段水平扫到 \((0, N-L), (L, N-L)\),并把途径的所有点全部推到 \(y = N-L\)。
- 加入一个新的点,位置为 \((X, Y)\),设上一个点的编号为 \(c\),则这个点的编号为 \(c+1\)。
\(1 \le N \le 10^9, 1 \le m \le 5 \times 10^5, 1 \le q \le 10^6\)。
sub 2:操作类型只有 \(1,2,4\);sub 3:满足操作类型只有 \(1,2,3\),且 \(x_i \le x_{i+1}, y_i\ge y_{i+1}\);sub 4:操作类型只有 \(1,2,3\)。
Subtask 2,没有过程 V,显然问题中你只需要关心 \(x\) 坐标的变化,容易用线段树维护。这启示一维上的问题是好做的。
Subtask 3,考察性质:随着 \(x\) 增大,\(y\) 不断减小,也就是长成:\(\ddots\)。显然,在过程中这个性质不会被破坏,用一个线段树上二分 + 区间赋值即可做。
Subtask 4,与 Sub 3 的区别只有少了一个性质,考虑什么情况下这个性质又成立了。容易发现,所有被推过一次的点天然满足性质,可以直接像刚刚一样二分做;考虑找到每个点第一次被推的时候,容易发现是一个二维偏序的关系,扫描线就能够找到。然后考虑问题变成每次插入一个点,支持按照 \((x, y, id)\) 三个关键字排序(防止出现无法比较的情况)和区间赋值操作,所以就不好使用线段树了,最好用平衡树写。
考虑正解,Subtask 4 是不支持插入新点的,花费一个 \(\log q\) 的代价,用线段树分治去除掉插入新点的操作。把新点的存在拆成 \(\log n\) 个区间,在每个节点上做 Subtask 4 即可,时间复杂度 \(O((m + q)\log q \log (m + q))\)。常数巨大,但在 11s 时限内应该能够跑过;积极复用可以做到空间复杂度 \(O(q \log q)\),但常数也比较大。
Subtask 4 的提示使问题变成了一个一维问题,因为 \(x, y\) 的单调性恰好相反,一个排序后另一个也有序了,所以不需要同时管辖两维,启发性极强。
进一步考察性质发现不需要写平衡树,把每个点推一次过后的点拉出来排序,每次修改只会对一段前缀或一段后缀做取 max 的修改(对于一段区间赋值),可以用 odt 做,但是不是很好写因为需要二分,可能要开两个 set,常数不小且细节较多。

浙公网安备 33010602011771号