扫描线
有些题目可以直接使用数据结构解决;但有时还有额外的一维约束条件需要被满足,这时候就可以考虑离线、排序,使用扫描线压掉这一维;剩下的子问题就可以使用数据结构求解了。
例题
P5490 【模板】扫描线 & 矩形面积并
题目大意
给定 \(n\) 个矩形,求其并集的面积。
我们将每个矩形 \((x_1,y_1,x_2,y_2)\) 都拆分成两条带权的线段:\((x_1,y_1,y_2,1)\) 和 \((x_2,y_1,y_2,-1)\)。那么问题本质就是求每个 \(x\) 处,位于其左边的所有线段的并集的总长度是多少。这实际上是 \(1\) 维的约束,但重合部分的处理需要使用数据结构,因此需要使用扫描线把 \(x\) 维度压掉。
先离线处理出所有线段,按 \(x\) 排序;接着依次遍历每条线段:
- 在线段树中查询 \(>0\) 的值的个数 \(num\),它们对答案有 \(num\times(line[i].x-line[i-1].x)\) 的贡献;
- 在线段树中对 \([y_1,y_2]\) 进行区间 \(+1\) 或区间 \(-1\)。
如何使用线段树求出 \(>0\) 的值有多少个呢?我们用线段树同时维护区间最小值和区间最小值出现的次数。如果区间最小值等于 \(0\),那么最小值出现的次数就是 \(0\) 出现的次数。用区间长度减去 \(0\) 出现过的次数即可。
注意事项:
- 由于题目中提供的是每个矩形四个顶点的几何坐标。若要转化为可以用线段树维护的网格坐标,需要将闭区间 \([y_1,y_2]\) 转换为右半开区间 \([y_1,y_2)\)
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
|
P1856 [IOI1998] [USACO5.5] 矩形周长Picture
题目大意
给定 \(n\) 个矩形,求其并集的周长。
考虑改进矩形面积并的思路。观察样例不难发现,可以先统计所有横向的边的贡献,再统计所有竖向的边的贡献。
我们先考虑处理竖向边的贡献(横向边同理)。我们注意到:
- 有一条权值为 \(+1\) 的边 \((x_i,y_{i,1},y_{i,2})\),设区间 \([y_{i,1},y_{i,2}]\) 有 \(k\) 个位置为 \(0\),则这条边就会产生 \(k\) 的贡献。
- 有一条边权为 \(-1\) 的边 \((x_i,y_{i,1},y_{i,2})\),则先给区间 \([y_{i,1},y_{i,2}]\) 减 \(1\),再统计此区间内 \(0\) 的数量,记为 \(k\),则这条边就会产生 \(k\) 的贡献。
本题用普通线段树维护即可。时间复杂度 \(O(n\log n)\)。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
|