(线段树 + 扫描线)洛谷模板题

1|0原题链接:

洛谷扫描线模板

2|0题目描述:

求 n 个矩形的面积并。
第一行输入一个整数n,随后的n行依次输入x1,y1,x2,y2, (x1,y1),(x2,y2)分别代表矩形的左下角坐标和右上角坐标。

输入格式:
2
100 100 200 200
150 150 250 255
输出格式:
18000
说明:
1≤n≤10000,
0≤x1<x2≤1e9,
0≤y1<y2≤1e9.

3|0思路:

#include<bits/stdc++.h> using namespace std; #define endl '\n' #define int long long typedef pair<int, int> PII; const int mod = 1e9 + 7; const int inf = 0x3f3f3f3f; const int N = 1e5 + 10; int n, m; struct Segment{ //存储操作 int x, y1, y2; int k; //k 是矩形的边界,1 -- 左边界,-1 -- 右边界 }seg[N << 1]; struct Node{ int l, r; int cnt; int len; }tr[N << 3]; //线段树要开四倍空间,每条线段有两点,所以是八倍 vector<int> ys; //离散化数组 bool cmp(Segment &a, Segment &b){ //将操作按横坐标从小到大排序 return a.x < b.x; } int find(int y){ //返回纵坐标离散化后的值 return lower_bound(ys.begin(), ys.end(), y) - ys.begin(); } void pushup(int u){ if(tr[u].cnt) tr[u].len = ys[tr[u].r + 1] - ys[tr[u].l]; //如果结点上有线段覆盖,那他被覆盖的长度就是y轴上的坐标之差 else if(tr[u].l != tr[u].r){ tr[u].len = tr[u << 1].len + tr[u << 1 | 1].len; //如果不是叶子节点,则将覆盖的长度往上传 } else tr[u].len = 0; //如果是叶节点, 那么len = 0 } void build(int u, int l, int r){ //基本的建树操作 tr[u].l = l, tr[u].r = r; if(l == r) return ; int mid = l + r >> 1; build(u << 1, l, mid); build(u << 1 | 1, mid + 1, r); } void modify(int u, int l, int r, int k){ if(tr[u].l >= l && tr[u].r <= r){ //如果所操作的区间包含在该结点内,则对cnt += k tr[u].cnt += k; pushup(u); //操作完更新父节点 } else{ int mid = tr[u].l + tr[u].r >> 1; if(l <= mid) modify(u << 1, l, r, k); if(r > mid) modify(u << 1 | 1, l, r, k); pushup(u); //操作完更新父节点 } } signed main(void){ ios::sync_with_stdio(false); cin.tie(0); cin >> n; for(int i = 0, j = 0; i < n; i++){ int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2; seg[j ++] = {x1, y1, y2, 1}; seg[j ++] = {x2, y1, y2, -1}; ys.push_back(y1), ys.push_back(y2); } sort(ys.begin(), ys.end()); //排序 ys.erase(unique(ys.begin(), ys.end()), ys.end()); //去重(离散化) build(1, 0, ys.size() - 2); sort(seg, seg + n * 2, cmp); int res = 0; for(int i = 0; i < n * 2; i++){ if(i > 0) res += tr[1].len * (seg[i].x - seg[i - 1].x); modify(1, find(seg[i].y1), find(seg[i].y2) - 1, seg[i].k); } cout << res << endl; return 0; }

__EOF__

本文作者ReSakura
本文链接https://www.cnblogs.com/ReSakura/p/16212919.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   ReSakura  阅读(60)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示