EVERYTHING HAPPENS FOR THE BE|

wnsyou

园龄:2年4个月粉丝:19关注:16

2024-09-09 20:10阅读: 15评论: 0推荐: 0

扫描线

OI-wiki Link

引入

先来看一道题:油漆面积

给出若干个矩形,求这些矩形的面积并。

这题数据范围很小,用一个二维差分就行了。

那把范围调大呢?(即模板扫描线)

这个时候就需要使用线段树来维护扫描线了。

思想

想象一下,在平面直角坐标系上面有很多个矩形,有一条线从底部开始往顶部进行扫描,每次统计在 y 坐标的一个区间内且每行被至少一个矩形覆盖的部分完全相同的部分对于答案的贡献。

图片来源 OI-wiki

这个要怎么维护呢?尝试把矩形变成两条线段去做贡献,当扫描线扫到一个矩形的下底时,会使得这个矩形对应的 x 坐标区间内每个元素都加一,同理扫到上底的时候每个元素都要减一。这就变成了区间修改。

那么算贡献呢?只要知道有多少元素为正数,用线段树去维护即可。

由于模板数据范围较大,需要离散化,注意处理边界的细节。

Code

用的永久化标记的写法。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5 + 10;
struct Edge {
int h, x, y, z;
} e[N];
struct SegTree {
int l, r, cov, len;
} tr[N * 8];
int n, dce[N], dce_[N], dcnt, ally[N];
ll ans;
void pushup (int id) {
// tr[id].cov = min(tr[id * 2].cov, tr[id * 2 + 1].cov);
if (tr[id].cov)
tr[id].len = tr[id].r - tr[id].l;
else
tr[id].len = tr[id * 2].len + tr[id * 2 + 1].len;
}
void build (int id, int l, int r) {
tr[id] = {dce_[l], dce_[r + 1]};
if (l == r)
return ;
int mid = (l + r) >> 1;
build(id * 2, l, mid), build(id * 2 + 1, mid + 1, r);
}
void modify (int id, int l, int r, int x, int y, int z) {
if (x <= tr[id].l && tr[id].r <= y) {
tr[id].cov += z, pushup(id);
return ;
}
if (y < tr[id].l || tr[id].r < x)
return ;
int mid = (l + r) >> 1;
modify(id * 2, l, mid, x, y, z), modify(id * 2 + 1, mid + 1, r, x, y, z);
pushup(id);
}
int main () {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for (int i = 1, x1, y1, x2, y2; i <= n; i++) {
cin >> x1 >> y1 >> x2 >> y2, dce[i * 2 - 1] = x1, dce[i * 2] = x2;
e[i * 2 - 1] = {y1, x1, x2, 1}, e[i * 2] = {y2, x1, x2, -1};
ally[i * 2 - 1] = y1, ally[i * 2] = y2;
}
n *= 2, sort(dce + 1, dce + n + 1), sort(e + 1, e + n + 1, [](const Edge &i, const Edge &j){return i.h < j.h;}), sort(ally + 1, ally + n + 1), dce[0] = -1;
for (int i = 1; i <= n; i++)
if (dce[i] != dce[i - 1])
dce_[++dcnt] = dce[i];
build(1, 1, dcnt - 1);
for (int i = 1, j = 1; i < n; i++) {
for (; j <= n && e[j].h == ally[i]; j++)
modify(1, 1, dcnt - 1, e[j].x, e[j].y, e[j].z);
ans += 1ll * (ally[i + 1] - ally[i]) * tr[1].len;
}
cout << ans;
return 0;
}

本文作者:wnsyou の blog

本文链接:https://www.cnblogs.com/wnsyou-blog/p/18302418/scanning

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   wnsyou  阅读(15)  评论(0编辑  收藏  举报
  1. 1 勝利への道 安藤浩和
  2. 2 Minecraft’s End Eric Fullerton
  3. 3 月光曲完整版 贝多芬 云熙音乐
  4. 4 平凡之路 (Live版) 朴树
  5. 5 Minecraft C418
  6. 6 Paradise NiziU
  7. 7 叫我,灰原哀 龙大人不喷火
  8. 8 心机之蛙,一直摸你肚子 ——《名侦探柯南》原创同人曲 炊饭,叶辞樱,温海,寒砧,南柯柯,小茜玛姬,盛姝,阿崔Ac,贝壳初,千湛,兮茶子DaYu,乔慕,黎鹿北,起千温卿,遮阳伞,曲悠
  9. 9 战 歌 此去经年
战 歌 - 此去经年
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 此去经年

作曲 : 此去经年

编曲 : 此去经年

啊啊啊啊啊

啊啊啊啊

啊啊啊

啊啊

加载中…

{{tag.name}}

{{tran.text}}{{tran.sub}}
无对应文字
有可能是
{{input}}
尚未录入,我来提交对应文字
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示