题解 CF983D Arkady and Rectangles

\(\texttt{link}\)

题意

平面直角坐标系上给定 \(n\) 个矩形,第 \(i\) 个矩形颜色为 \(i\),颜色大的矩形将覆盖颜色小的矩形,问最后能看到几种颜色。

\(1\le n\le 10^5,|x_i|,|y_i|\le 10^9\)

题解

首先离散化,考虑扫描线如何维护序列上的颜色。

一个区间 \([l,r]\) 投射到线段树上 \(O(\log n)\) 个不交区间,总共 \(O(n\log n)\) 个。对于每个区间,直接把每种颜色塞到一个 set 里,当前区间可能被看到的颜色只会是 set 最大值,记为 \(v_x\)

考虑只插入怎么做,发现 \(i\) 处的颜色即线段树上根节点到 \([i,i]\) 路径上每个 \(v_x\)\(\max\),那我在一个被颜色 \(c\) 完全覆盖的区间 \([l,r]\) 上,若根到 \([l,r]\) 路径上的 \(\max v_x\) 小于 \(c\),且存在该节点到某一叶节点的路径 \(\max v_x\) 也小于 \(c\),说明 \(c\) 可被看到,于是在线段树上维护 \(mn_x\) 表示所有 \(x\) 到叶节点的路径 \(\max v_x\) 的最小值,即可 \(O(1)\) 判断,每次最多增加 \(1\) 个新颜色。

现在加入删除操作,一个区间的删除可能会增加更多可被看到的颜色,但答案最多 \(O(n)\) 个,那我设法只考虑没被看过的颜色,用 \(mx_x\) 表示以 \(x\) 为根的子树,没被统计过且可能会被看见的最大颜色,从 \([l,r]\) 中删掉颜色 \(c\),重新计算 \(v_x\)。pushup 时先继承左右儿子,考虑 \(v_x\)\(mn_x\)\(mx_x\) 的贡献,分两种情况:

  • \(v_x\) 已被统计过,\(mn_x\gets\max(mn_x,v_x)\)

  • \(v_x\) 未被统计过,\(mx_x\gets\max(mx_x,v_x)\)

\(mn_x>mx_x\),即当前区间可能会被看见的最大颜色比 \([l,r]\) 中已被看见的最小颜色还小,越往上走 \(mn_x\) 只增不减,自然看不见 \(mx_x\) 了,令 \(mx_x\gets 0\)

\(mx_1\ne 0\),说明出现了一种从未被看见的颜色被看到了,标记为已看见,并把 \(mx_1\) 对应的 \(O(\log n)\) 个区间拉出来修改信息。若修改后 \(mx_1\) 仍不为 \(0\),就继续修改,直到 \(mx_1=0\)。因为最多只有 \(n\) 个颜色,所以总修改次数最多 \(n\) 次。

线段树一个 \(\log\),set 一个 \(\log\),时间复杂度 \(O(n\log^2 n)\)

posted @ 2024-02-27 20:40  Terac  阅读(13)  评论(0)    收藏  举报