首页 > 其他分享 >扫描线小复习

扫描线小复习

时间:2023-07-18 17:36:46浏览次数:47  
标签:rt 复习 tree xd long 扫描线 矩形

扫描线

目录

思想

扫描线的思想十分简单,就是把矩形分为多次小的矩形求解罢了,关键在于实现
记得有一次周考就写挂了......

实现

首先想要正好不重不漏地扫过一个矩形(只有一个的情况下)而不影响其他非矩形地方的方法是什么?
假设我扫描线是从下往上扫的,那么对于这个矩形而言,我在遇到下边的时候权值+1,遇到上边时权值-1
为了保证左侧和右侧不会扫过头(不会扫过其宽度),那么我应该维护这个线段区间权值+1-1.
为了求解面积,我不可忽略这个矩形的高度,换句话说,这个状态应该是持续性的(扫描有过程),而持续的时间就是高度
而这种区间的维护我可以利用线段树完成

现在扩展到有重叠的多个矩形,发现如果+1这样的话,可能某些区间会达到2/3/4等等等等,但是面积我应该只计算1
所以我线段树中应该维护两个值:重叠次数和贡献
贡献只有0/1之分,而重叠次数可以有很多
当且仅当重叠次数=0时,贡献为0
差不多就行了吧,注意排序即可。
然后离散化的话,就需要一个映射关系
例如在线段树上节点x对应[X[tree[x].l],X[tree[x].r+1]]这条横边

代码:

#include <bits/stdc++.h>
//#define int long long
using namespace std;
struct xd{
	long long l;
	long long r;
	long long hi;
	long long lz;//表示上边或下边 
}line[1000005];
struct node {
    long long sum;  //(被覆盖的次数 
    long long l;
    long long r;
    long long len;//表示长度(被截取后 ,即实际有效长度 
} tree[4000005];
long long X[1000005];
void build(long long rt,long long l,long long r){
	tree[rt].l=l;
	tree[rt].r=r;
    if(l==r){
    	return;
	}
    long long mid = (l + r) >> 1;
    build(rt*2, l, mid);
    build(rt*2+1, mid + 1, r);
    return;
} 
bool cmp(xd x,xd y){
	if(x.hi!=y.hi)return x.hi<y.hi;
	else return x.l<y.l;
}
void pushup(long long rt) {
    int l = tree[rt].l, r = tree[rt].r;
    if(tree[rt].sum)
    	tree[rt].len=X[r+1]-X[l];//实际长度 ,只要不为零,说明对整个面积有贡献,是被全部覆盖的  
    else
        tree[rt].len=tree[rt*2].len+tree[rt*2+1].len;//可能存在被部分覆盖的情况,需要看儿子的贡献 
}
void updata(int rt,long long L,long long R,long long c) {
    int l=tree[rt].l;
	int r=tree[rt].r;
    if(X[r+1]<=L||R<= X[l])
        return;
    if(L<=X[l]&&X[r+1]<= R) {
        tree[rt].sum+=c;
        pushup(rt);
        return;
    }
    updata(rt*2, L, R, c);
    updata(rt*2+1, L, R, c);
    pushup(rt);
}
int main() {
	ios::sync_with_stdio(false);
	long long n;
	cin >> n;
	for(long long i=1;i<=n;i++){
		long long a,b,c,d;
		cin >> a>> b>> c>> d; 
		X[i*2-1]=a;
		X[i*2]=c;
		line[i*2-1]=(xd){a,c,b,1};
		line[i*2]=(xd){a,c,d,-1};
	}
    n<<=1;
    sort(X+1,X+1+n);
    sort(line+1,line+1+n,cmp);
    int tot = unique(X + 1, X + n + 1) - X - 1;//去重,tot表示去重后的个数
	//补充下,unique(a,b)-a表示找a-b的非重复个数,并更新去重的数组;(大概? 
	build(1,1,tot-1);//右边的没了 
	long long ans=0;
	for(int i=1;i<n;i++){
		updata(1,line[i].l,line[i].r,line[i].lz);
        ans+=tree[1].len*(line[i + 1].hi-line[i].hi);
//        cout<<ans<<endl;
	}
	cout<<ans;
}

标签:rt,复习,tree,xd,long,扫描线,矩形
From: https://www.cnblogs.com/linghusama/p/17563591.html

相关文章

  • 铃狐sama的竞赛复习(持续更新)
    铃狐sama的竞赛复习计划目录铃狐sama的竞赛复习计划dfs,bfs的整体复习题目来源可如下:null数论复习,以下还要求掌握原理,暂时放在最后一起复习,记忆深刻一点gcd熟练掌握exgcd必须要求熟练背诵phi欧拉函数必须要求熟练背诵欧拉筛法必须要求熟练背诵卷积要求再进行熟练掌握整数分块要求......
  • 复习-基础课-基础算法
    1.快速排序:不稳定,其他略。2.归并排序:稳定,常用于求逆序对。voidmsort(intl,intr){if(l>=r)return;intmid=(l+r)>>1;msort(l,mid);msort(mid+1,r);//递归排序intk=0;inti=l,j=mid+1;while(i<=mid&&j<=......
  • 搜索和图论_复习
    DFSAcWing842.排列数字代码#include<bits/stdc++.h>usingnamespacestd;typedefpair<int,int>PII;constintN=10;intpath[N];boolst[N];intn;voiddfs(intx){if(x>n)return;for(inti=1;i<=n;i++){if(st[i]==1)continu......
  • 笔试复习
    NOI2023是第40届,IOI2000是第12届,在北京。kill仅对PID生效,killall用于进程名字。删除目录:rm-r。linux区分大小写。查看隐藏文件:ls-a。高级语言的程序是源程序,不是源代码!只编译生成目标文件的命令行选项是:-c。指定输出文件名的命令行选项是:-o。在Linux的各个......
  • 复习结构体的创建,重定义,打印,以及对函数压栈的理解
    函数在操作,在栈上进行,形参的拷贝和函数的运行,基本上都在栈上完成,所以结构体的传参,对栈区的资源消耗较大。而传地址的操作则会节省栈区资源,不需要形参的拷贝过程,而是直接寻址。#define_CRT_SECURE_NO_WARNINGS1#include"stdio.h"structT{ chart; chars;};typedefstruc......
  • NOI 2023 考前知识点总复习
    NOI2023考前知识点总复习其实就是把熟悉或不熟悉的东西再过一遍,防止考场上出现会了做法却因为忘了算法而写不出来的问题。可能会一句话概括,也可能附上一点代码片段。如果不想复习知识点,只想要一点考前提示,可以直接翻到本文最底部。目录I.数据结构、树上问题II.数论III.......
  • vue和servlet 前后端分离 (复习)
    一、vue复习1.vue的使用步骤:(1)导入vue.js(2)创建除body以外最大的div标签,给定id值(3)创建vue对象newVue({el:"#app",data:{}//定义变量methods:{}//定义方法2.vue语法:v-bind:value(:value),v-model:value="",v-if,v-show,v-for的使用......
  • 数学复习 定积分的应用
    这里主要复习积分的几何应用首先按应用情况进行梳理:(1)求平面图形的面积这部分的应用分为平面直角坐标和极坐标两种情况平面直角坐标的情况:当对x积分时,其取微分的方法是取长为f(x)-g(x),宽为dx的小矩形极坐标的情况在这种方法中,取微分的方法是取角度为dθ的狭窄的小扇形,整......
  • 扫描线 - 知识点梳理
    扫描线算法可解决平面内平行坐标轴的线段有关的问题,例如求平面上平行于坐标轴的矩形的面积并,其原理在于模拟一条扫描线从下往上扫描。线段树是一种灵活的LeafyTree,可以灵活地扫描线上统计线段的分布情况,将一部分信息储存在分支节点上,另一部分信息下传至叶子节点,因此线段树是扫描......
  • C++进制转换+扫描线算法(二维区间合并面积和)
    ......