线段树-扫描线
这其实是计算几何的一部分。一般被用来解决图形面积、周长等问题。
Atlantis 问题(板题)
题意
求给定的 个矩形的面积并
解法
如图:
-
每一块颜色不同的部分都是一个矩形,这 个矩形的面积并就是重新划分后各个颜色的矩形的面积和
-
扫过的距离 乘 当前的宽度就是当前矩形的面积
(从左到右扫)
若一个矩形的左下顶点坐标为 ,右上顶点坐标为
-
将它的左沿和右沿两条边存成一个四元组;左:,右: 。最后的标记: 表示加入这条边; 表示减去这条边
-
将 个矩形都这样做处理,就得到 条边,把这 条边按照 的大小从小到大排序
-
因为数据可能很大而且不一定是整数,所以要对 进行 离散化 处理
模板代码
#include<bits/stdc++.h> using namespace std; #define int long long const int N=1e5+5; int n; double ls[N<<1]; struct line{ int x,y1,y2,mrk; }a[N<<4]; struct node{ int l,r,sum,len;//sum:被完全覆盖的次数 ; len:被选取的长度 }tr[N<<4]; bool cmp(line x,line y){ return x.x<y.x; } void build(int node,int l,int r){ tr[node].l=l,tr[node].r=r; tr[node].len=0; tr[node].sum=0; if(l==r) return; int mid=(l+r)>>1; build(node<<1,l,mid); build(node<<1|1,mid+1,r); return; } void pushup(int node){ int l=tr[node].l,r=tr[node].r; if(tr[node].sum) tr[node].len=ls[r+1]-ls[l]; else tr[node].len=tr[node<<1].len+tr[node<<1|1].len; } void change(int node,int l,int r,int x){ int L=tr[node].l,R=tr[node].r;//L,R与l,r 意义完全不同 if(ls[R+1]<=l || ls[L]>=r)//R+1才能覆盖完区间 return; if(l<=ls[L] && r>=ls[R+1]){ tr[node].sum+=x; pushup(node); return; } change(node<<1,l,r,x); change(node<<1|1,l,r,x); pushup(node); } signed main(){ cin>>n; for(int i=1;i<=n;++i){ int x1,y1,x2,y2; cin>>x1>>y1>>x2>>y2; a[i*2-1].x=x1,a[i*2-1].y1=y1,a[i*2-1].y2=y2; a[i*2].x=x2,a[i*2].y1=y1,a[i*2].y2=y2; a[i*2-1].mrk=1,a[i*2].mrk=-1; ls[i*2-1]=y1,ls[i*2]=y2; } n<<=1;//后面用起来方便 sort(a+1,a+n+1,cmp); sort(ls+1,ls+n+1);//离散化 int tot=unique(ls+1,ls+n+1)-ls-1;//去重 ls[tot+1]=0x3f3f3f3f; build(1,1,tot);//建树 int ans=0; for(int i=1;i<n;++i){ change(1,a[i].y1,a[i].y2,a[i].mrk); ans+=tr[1].len*(a[i+1].x-a[i].x); } cout<<ans; return 0; }
拓展题目
本文作者:_yolanda
本文链接:https://www.cnblogs.com/yolanda-yxr/p/15896440.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步