扫描线

用于计算若干个矩形的并的面积或周长及其延伸出来的问题。思想形象点来说大概就是将二维平面的某一维离散化后上线段树,然后按照一定顺序(一般是从小到大)扫描,同时维护树上信息(一般是当前区间内图形与扫描线交的长度)。
比普通线段树特殊的几点:
1.一般不需要特定的query函数,一般直接取根节点的值即可;
2.一般不需要下放标记,因为不会跳过一个父区间去访问一个子区间。但具体问题要具体对待。
3.l一般代表[l,l+1) 这个区间,所以某些地方的树上位置要相比实际位置-1。

求矩形交的面积

例题

将矩形与x轴平行的边上树,动态维护某些区间边的存在性,乘以当前操作与上个操作的y坐标之差,求和即为矩形面积的答案。(实质上是将矩形分割成了若干个小矩形)。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
unordered_map<int,int> getx;
int n,back[maxn];
struct SG{
	int xl,xr,y,opt;
	SG(){}
	SG(int _xl,int _xr,int _y,int _opt){
		xl=_xl,xr=_xr,y=_y,opt=_opt;
	}
}sg[maxn];
inline bool cmp(SG aa,SG bb){
	if(aa.y!=bb.y) return aa.y<bb.y;
	return aa.opt>bb.opt;
}
int cunx[maxn],cnt;
#define lc(u) (u<<1)
#define rc(u) (u<<1|1)
int t[maxn<<4],lt[maxn<<4];
inline void pushup(int u,int l,int r){
	if(lt[u]) t[u]=back[r+1]-back[l];
	else if(l==r) t[u]=0;
	else t[u]=t[lc(u)]+t[rc(u)];
}
inline void update(int u,int ul,int ur,int l,int r,int k){
	if(ul==l&&ur==r){
		lt[u]+=k;
		pushup(u,l,r);
		return;
	}
	int mid=(l+r)>>1;
	if(ul<=mid) update(lc(u),ul,min(ur,mid),l,mid,k);
	if(ur>mid) update(rc(u),max(mid+1,ul),ur,mid+1,r,k);
	pushup(u,l,r);
}
signed main(){
	//freopen("P5490_1.in","r",stdin);
	//freopen("1.out","w",stdout);
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1,xl,xr,yu,yd;i<=n;i++){
		cin>>xl>>yd>>xr>>yu;
		sg[i]={xl,xr,yd,1},sg[i+n]={xl,xr,yu,-1};
		cunx[i]=xl,cunx[i+n]=xr;
	}
	sort(cunx+1,cunx+2*n+1);
	cunx[0]=-1;
	for(int i=1;i<=2*n;i++)
		if(cunx[i]!=cunx[i-1]) ++cnt,getx[cunx[i]]=cnt,back[cnt]=cunx[i];
	sort(sg+1,sg+2*n+1,cmp);
	ll ans=0;
	update(1,getx[sg[1].xl],getx[sg[1].xr]-1,1,cnt-1,sg[1].opt);
	for(int i=2;i<=2*n;i++){
		ans+=1ll*t[1]*(sg[i].y-sg[i-1].y);
		update(1,getx[sg[i].xl],getx[sg[i].xr]-1,1,cnt-1,sg[i].opt);
	}
	cout<<ans;
	return 0;
}

求矩形并的周长

思想差不多,只不过同一条线段的贡献可能会被重复计算,所以每次就是将存在线段的区间长减去上一个操作后存在线段的区间长的绝对值相加。

扩展应用

例题

我们可以把点扩大成矩形,在给定范围内,若某些点代表的矩形有交,则说明这些点能被同一个矩形包含。将矩形的权值设为点权即可,然后答案就是区间取max。然后这里要记得下放标记。

posted @ 2025-10-19 14:19  _dlwlrma  阅读(12)  评论(2)    收藏  举报