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

扫描线学习笔记

时间:2024-08-03 22:40:19浏览次数:15  
标签:ll tree mid 笔记 学习 二维 扫描线 sum

前言

扫描线思想可以在 \(O(n^2)\) 的时间复杂度内进行二维平面的计算,运用线段树优化可以在 \(O(n \log n)\) 的时间复杂度内解决。

简介

P5490 【模板】扫描线

以此题为例,介绍扫描线。

最直接的想法是将每个正方形的面积先加起来,最后再减去重叠部分,但是代码难度较大,不易于实现。

用扫描线的思想,将二维转换为两个一维。对于 y 轴的一维,从下往上进行扫描,每一条扫描线就是矩形的长,用结构体记录起始终止的 x 值,以及 y 值,还有标记是矩形的上面长还是下面的长。

对于从左到右的另一维 x,用线段树维护每一个中间的区间,遇到扫描线时进行统计计算即可。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e6+20;
ll n,x_,x__,y_,y__,X[maxn],ans;
struct smx{
	ll l,r,h,flag;
	inline bool operator < (const smx &T) const{
		return h<T.h;
	}
}line[maxn];
struct segment{
	ll l,r,sum,cnt;
}tree[maxn<<3];
inline ll ls(ll p){
	return p<<1;
}
inline ll rs(ll p){
	return p<<1|1;
}
void build(ll p,ll l,ll r){
	tree[p].l=l,tree[p].r=r,tree[p].sum=tree[p].cnt=0;
	if(l==r) return;
	ll mid=l+r>>1;
	build(ls(p),l,mid);
	build(rs(p),mid+1,r);
} 
inline void push_up(ll p){
	if(tree[p].cnt){
		tree[p].sum=X[tree[p].r+1]-X[tree[p].l];
	}
	else tree[p].sum=tree[ls(p)].sum+tree[rs(p)].sum; 
}
void update(ll p,ll l,ll r,ll x,ll y,ll k){
	if(X[r+1]<=x||X[l]>=y) return;
	if(X[l]>=x&&X[r+1]<=y){
		tree[p].cnt+=k;
		push_up(p);//一定要写这行!!! 
		return;
	}
	ll mid=l+r>>1;
	update(ls(p),l,mid,x,y,k);
	update(rs(p),mid+1,r,x,y,k);
	push_up(p);
}
int main(){
	scanf("%lld",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld%lld%lld%lld",&x_,&y_,&x__,&y__);
		X[i*2-1]=x_,X[i*2]=x__;
		line[i*2-1]=(smx){x_,x__,y_,1},line[i*2]=(smx){x_,x__,y__,-1};
	}
	n<<=1;
	sort(line+1,line+n+1);
	sort(X+1,X+n+1);
	ll tot=unique(X+1,X+n+1)-X-1;
	build(1,1,tot-1);
	for(int i=1;i<n;i++){
		update(1,1,tot-1,line[i].l,line[i].r,line[i].flag);
		ans+=(line[i+1].h-line[i].h)*tree[1].sum;
	}
	printf("%lld\n",ans);
	return 0;
} 

总结

可见扫描线可以处理二维的问题,所以遇到一些平面内的二维数点计算问题时,可以尝试用扫描线求解。

标签:ll,tree,mid,笔记,学习,二维,扫描线,sum
From: https://www.cnblogs.com/dayz-break/p/18341245

相关文章

  • 矩阵学习笔记
    矩阵引入矩阵引入来源于简洁表示线性方程组例如:\[\begin{cases}2x+5y=10\\4x+9y=39\end{cases}\]可以表示为:\[\begin{bmatrix}2&5\\4&9\end{bmatrix}\times\begin{bmatrix}x\\y\end{bmatrix}\]矩阵乘法定义矩阵\(A\)为\(n\timesm\)的矩阵,\(B\)为\(......
  • 树的基础学习笔记
    树的直径定义:树上最长的简单路径。(可能有多条)树的直径的性质直径两端点一定是两个叶子节点。距离任意点最远的点一定是直径的一个端点,这个基于贪心求直径方法的正确性可以得出。对于两棵树,如果第一棵树直径两端点为(u,v),第二棵树直径两端点为\((x,y)\),用条边将两棵树......
  • OpenStack Yoga版安装笔记(十二)nova安装(下)
    5、InstallandconfigurecontrollernodeforUbuntu注意安装版本为:nova25.2.2.dev55.1Prerequisites在安装和配置compute service之前,需要先创建数据库、服务凭证(用户名/密码)、服务API端点。1、Createthedatabase:root@controller:~#mysqlWelcometotheMariaDB......
  • 科大讯飞学习机s30和t20pro区别对比
    1,屏幕二款都采用了高清类纸护眼屏,S30屏幕尺寸12英寸,分辨率2K,屏幕刷新率60Hz;T20Pro屏幕尺寸13.3英寸,分辨率2.5k,屏幕刷新率90Hz。2,处理器S30采用AI双引擎八核学习芯片;T20Pro搭载的是AI三引擎八核学习芯片。3,存储空间S30是8+256G;T20Pro8+512G。4,电池容量S30采用的7500mAh......
  • 嵌入式学习day9(string函数族)
    一丶strcpy和strncpy1.strcpy    #include<string.h>    char*strcpy(char*dest,constchar*src);    功能:实现字符串复制    参数:char*dest:目标字符串首地址    constchar*src:原字符串首地址    返回值:目标字符串首地......
  • Java学习第五周
    packagecom.sxt;publicclassTestSwitch01{publicstaticvoidmain(String[]args){intgrade=(int)(Math.random()*4)+1;//大学的年级switch(grade){case1:System.out.println("大一");break;case2:System.out.println("大二");break;case3:......
  • 学习Java第五周
    本周学习一、类的继承1.继承特点修饰符classSubClassextendsSuperClass{//类定义部分}表明继承了SuperClass类。注:子类只能从被扩展的父类获得成员变量、方法和内部类(包括内部接口、枚举),不能获得构造器和初始化块。2.Java类只能有一个直接父类,实际上,Java类可以有......
  • Python学习笔记51:暂停篇
    随便写点最近因为公司项目的原因,学习进度变慢很多,但是也勉强支撑着把小游戏的项目写了个大概,其实后续很多的功能基本都是慢慢添加就可以,掌握了函数的调用,磕磕碰碰终究还是能把功能写好的,可能就是代码质量差一点,但是这个没必要过于纠结,写的多了看的多了,慢慢的就会进步。一......
  • Windows令牌窃取提权和烂土豆提权学习
    令牌,又叫token,是系统临时产生的秘钥,相当于账号密码,用来决定是否允许此次请求和判断此次请求是属于哪一个用户。令牌无需提供密码或其他凭证,就可以访问网络和系统资源,这些令牌持续于系统中,除非系统重新启动。令牌的最大特点就是随机性,不可预测,无法猜解。当不同的用户登录计算机......
  • 8.3学习周记
    一.C语言学习1.数值输出(以整数为例):数值占3位%3d默认为右对齐左对齐要加负号变为%-3d2.字符串相关函数的学习:(数组1指向字符串1,数组2指向字符串2)a.strstr函数:strstr函数搜索字符串1是否在字符串2中出现,若未搜索到,则返回NULL;若搜索到,则该函数返回第一次出现s2的地址。b.strcpy......