首页 > 其他分享 >扫描线学习笔记

扫描线学习笔记

时间:2023-08-08 09:02:43浏览次数:37  
标签:y2 point int 笔记 学习 sgmt 扫描线 y1 now

0. 写在前面

扫描线好闪,拜谢扫描线

1. 问题的引入

在一个二维的坐标系上,给出多个矩形,求他们的面积并

2. 问题的分析

假设我们有这么一张图

你要求这三个矩形的面积并,可以考虑容斥原理,但这样会 TLE

但总之,他最终的结果是围成了一个多边形

那你不妨考虑,重新分割这个最终的图形

那这样你就很会求了。

考虑有一条线,从下往上扫描,如果遇到矩形的一条边就分割一次,OI Wiki 给出了一个很优秀的动图:

那么,你即是要考虑矩形的下端在哪里,矩形的上端在哪里,矩形的高是扫描线扫描的距离。我们使用线段树维护矩形的长,给每个矩形的上下边进行标记。下面标记为 \(1\) , 上面标记为 \(-1\),然后乘一下就好了。

#include <iostream>
#include <algorithm>
#include <cstring>
#define MAXN 1000001
#define int long long
#define ls(x) (x << 1)
#define rs(x) ((x << 1) + 1)
#define mid(l, r) ((l + r) >> 1)

using namespace std;

int lazy[MAXN << 3]; // 用于标记某条线段出现的次数
int s[MAXN << 3];
struct { int l, r, sum; } 	  sgmt[MAXN << 3];
struct node{ 
	int d, y1, y2, flag; 
	bool operator < (const node& x) const { return this->d < x.d;}
	node(int d, int y1, int y2, int flag) {	this->d = d, this->y1 = y1, this->y2 = y2, this->flag = flag; }
	node() {}
} point[MAXN << 3];

inline void pushup(int now) {
	if(lazy[now] > 0)  sgmt[now].sum = sgmt[now].r       - sgmt[now].l;
	else		       sgmt[now].sum = sgmt[ls(now)].sum + sgmt[rs(now)].sum;
}

void build(int now, int l, int r) {
	if(r - l > 1) sgmt[now].l = s[l], sgmt[now].r = s[r], build(ls(now), l, mid(l, r)), build(rs(now), mid(l, r), r), pushup(now);
	else 		  sgmt[now].l = s[l], sgmt[now].r = s[r], sgmt[now].sum = 0;
}

void upd(int now, int y1, int y2, int flag) {
	if(sgmt[now].l == y1 && sgmt[now].r == y2) lazy[now] += flag, pushup(now);
	else {
		if(sgmt[ls(now)].r > y1)   upd(ls(now), y1, min(sgmt[ls(now)].r, y2), flag);
		if(sgmt[rs(now)].l < y2)   upd(rs(now), max(sgmt[rs(now)].l, y1), y2, flag);
		pushup(now);		
	}
}
int n, ans;
signed main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n;
	for(int i = 0, x, y, u, v; i < n; ++ i) {
		cin >> x >> y >> u >> v;
		point[i] = {x, y, v, 1}, point[i + n] = {u, y, v, -1};
		s[i + 1] = y, s[i + 1 + n] = v;
	}
	sort(s + 1, s + rs(n)), sort(point, point + ls(n));
	build(1, 1, ls(n));
	upd(1, point[0].y1, point[0].y2, point[0].flag);
	for(int i = 1; i < ls(n); ++ i) {
		ans += (point[i].d - point[i - 1].d) * sgmt[1].sum;
		upd(1, point[i].y1, point[i].y2, point[i].flag);
	}
	cout << ans;
}

标签:y2,point,int,笔记,学习,sgmt,扫描线,y1,now
From: https://www.cnblogs.com/sdltf/p/17613246.html

相关文章

  • c#关于终止thread 学习经典
    C#多线程学习笔记之(abort与join配合使用)转载:************   原文中的评论,有便于理解的内容*************************C#多线程学习笔记之(abort与join配合使用)  今天刚开始学多线程,尽管以前用过一点点,但是只是照着网上代码抄,没有真正理解,现在回过头来想研究研究,......
  • tensorflow猫狗大战笔记
    第一步:数据集的加工importcv2importos#使用os.walk()函数遍历指定文件夹train及其所有子文件夹。dir='train'#读取图片路径的设定需要在程序文件里建立train文件夹将需要更改尺寸的图片放入forroot,dirs,filesinos.walk(dir):#forroot,dirs,filesinos.walk......
  • webpack学习
    目录1.Webpack的作用?2.Node中的CommonJS规范3.包管理工具-NPM4.Node的工具集-path/url/util/zlib5.Node的文件操作能力-fs6.Node的缓冲(Buffer)和流(stream)7.Node的事件机制-EventEmitter8.Node的HTTP处理-请求与响应9.Node的事件循环-EventLoop10.Node的进程集群-Cluster1.Webpack......
  • 【安全学习之路】Day41
    ......
  • Vue中Router笔记学习整理
    1:摘要:  Vue中的Router是Vue.js框架中的一个核心插件,用于实现单页应用(SPA)的前端路由管理。它允许你在应用中定义不同的URL路径与对应的组件之间的映射,以便在不刷新整个页面的情况下,实现页面间的切换和数据加载。主要功能包括以下几个方面:声明式路由:你可以通过定义路由......
  • 深度学习的一些基础函数
    上半年学习的一些记录主要参考的书:《写给新手的深度学习:用Python学习神经网络和反向传播》 Numpy:linspacereshape广播机制(数组在某一轴上扩展,值和原来一样,扩展之后可以和其他维度的数组做基本计算)切片transpose调换轴其中transpose(1,0)等价于T(转置)——略怪指定轴a......
  • k8s 学习笔记之数据存储——高级存储
    高级存储前面已经学习了使用NFS提供存储,此时就要求用户会搭建NFS系统,并且会在yaml配置nfs。由于kubernetes支持的存储系统有很多,要求客户全都掌握,显然不现实。为了能够屏蔽底层存储实现的细节,方便用户使用,kubernetes引入PV和PVC两种资源对象。PV(PersistentVolume......
  • 【刷题笔记】8. String to Integer (atoi)
    题目Implementthe myAtoi(strings) function,whichconvertsastringtoa32-bitsignedinteger(similartoC/C++'s atoi function).Thealgorithmfor myAtoi(strings) isasfollows:Readinandignoreanyleadingwhitespace.Checkifthenextcharact......
  • 『学习笔记』第二类斯特林数(部分)
    第二类斯特林数定义定义\(\begin{Bmatrix}n\\m\end{Bmatrix}\)表示\(n\)个互不相同的元素放入\(m\)个没有区分的集合并使这\(m\)个集合非空的方案数。其中\(\begin{Bmatrix}n\\m\end{Bmatrix}\)可读作“\(n\)子集\(k\)”。递推式\[\begin{Bmatrix}n......
  • 《Java编程思想第四版》学习笔记06
    为什么要把一个方法声明成final呢?正如上一章指出的那样,它能防止其他人覆盖那个方法。但也许更重要的一点是,它可有效地“关闭”动态绑定,或者告诉编译器不需要进行动态绑定。这样一来,编译器就可为final方法调用生成效率更高的代码。               ......