首页 > 其他分享 >扫描线

扫描线

时间:2024-07-19 21:44:53浏览次数:14  
标签:lazy int void cnt mid minx 扫描线

扫描线

把题目给的的区间想象成平面直角坐标系上的点. 再想象一条直线, 按顺序扫描获取信息, 维护信息

求出矩形面积并 :

把一个矩形看出两条平行于纵轴的边, 一条表示加入, 一条表示删除, 有很多区间的信息是一样的, 用乘法处理, 扫描线上的信息最多变动 \(2n\) 次

考虑用线段树维护, 考虑到区间的最小值 \(\ge 0\) 所以只需要维护一个区间最小值出现次数

例题 洛谷P5490

#include<bits/stdc++.h>

using namespace std;

const int N = 2e5 + 5;

struct Tr{
  int l, r, minx, cnt, lazy;
}t[N * 4];

struct Node{
  int x, y, y2, c;
}a[N];

long long ans;
int n, x[N], y[N], x2[N], y2[N], tot;
vector<int>e;

void renew(int p){
  t[p].minx = min(t[p * 2].minx, t[p * 2 + 1].minx);
  t[p].cnt = (t[p].minx == t[p * 2].minx) * t[p * 2].cnt + (t[p].minx == t[p * 2 + 1].minx) * t[p * 2 + 1].cnt;
}

void tog(int p, int L){
  t[p].lazy += L;
  t[p].minx += L;
}

void Lazy(int p){
  tog(p * 2, t[p].lazy);
  tog(p * 2 + 1, t[p].lazy);
  t[p].lazy = 0;
}

void build(int p, int l, int r){
  t[p].l = l, t[p].r = r;
  if(l == r){
    t[p].minx = 0, t[p].cnt = e[l] - e[l - 1];
    return;
  }
  int mid = (l + r) >> 1;
  build(p * 2, l, mid), build(p * 2 + 1, mid + 1, r);
  renew(p);
}

void updata(int p, int l, int r, int L){
  if(t[p].l >= l && t[p].r <= r){
    tog(p, L);
    return;
  }
  Lazy(p);
  int mid = (t[p].l + t[p].r) >> 1;
  if(l <= mid){
    updata(p * 2, l, r, L);
  }
  if(r > mid){
    updata(p * 2 + 1, l, r, L);
  }
  renew(p);
}

int getsum(int p, int l, int r){
  if(t[p].l >= l && t[p].r <= r){
    return (t[p].minx == 0 ? t[p].cnt : 0);
  }
  Lazy(p);
  int mid = (t[p].l + t[p].r) >> 1, sum = 0;
  if(l <= mid){
    sum += getsum(p * 2, l, r);
  }
  if(r > mid){
    sum += getsum(p * 2 + 1, l, r);
  }
  return sum;
}

int main(){
  cin >> n;
  for(int i = 1; i <= n; ++i){
    cin >> x[i] >> y[i] >> x2[i] >> y2[i];
    e.push_back(y[i]);
    e.push_back(y2[i]);
  }
  sort(e.begin(), e.end());
  for(int i = 1; i <= n; ++i){
    y[i] = lower_bound(e.begin(), e.end(), y[i]) - e.begin() + 1;
    y2[i] = lower_bound(e.begin(), e.end(), y2[i]) - e.begin();
    a[++tot] = {x[i], y[i], y2[i], 1}, a[++tot] = {x2[i], y[i], y2[i], -1};
  }
  build(1, 1, e.size() - 1);
  sort(a + 1, a + tot + 1, [](const Node &i, const Node &j){  return i.x < j.x;});
  for(int i = 1; i <= tot; ++i){
    ans += 1ll * (e.back() - e[0] - getsum(1, 1, e.size() - 1)) * (a[i].x - a[i - 1].x);
    updata(1, a[i].y, a[i].y2, a[i].c);
  }
  cout << ans;
  return 0;
}

时间复杂度 \(O(n \log n)\)

空间复杂度 \(O(n)\)

矩形周长并 :

思路 + 代码

标签:lazy,int,void,cnt,mid,minx,扫描线
From: https://www.cnblogs.com/liuyichen0401/p/18312420

相关文章

  • [University CodeSprint 4] Drawing Rectangles (扫描线 + 最小点覆盖)
    [UniversityCodeSprint4]DrawingRectangles扫描线+最小点覆盖题目的形式一看就是扫描线,观察到矩形的并面积\(\le3\times10^5\),所以可以直接把这些位置找出来。这部分的复杂度是\(O(n\logn)\)。然后剩下的部分就是一个经典的最小点覆盖问题。具体的说,构造二分图,左边代......
  • HDU 3642 (扫描线、三维体积相交)
    题意在三维空间中给你n个长方体,求空间中被这些长方体覆盖至少3次以上的区域的总体积。思路这题没给数据组数T的范围,大致看了一下其他人的都是枚举z来做的,所以我这边也是同样的做法转换成二维的扫描线来做,数组ci表示被覆盖i次的区间标记,具体扫描线怎么实现可以看我上篇博客。......
  • 扫描线
    扫描线引入扫描线一般运用在图形上面,它和它的字面意思十分相似,就是一条线在整个图上扫来扫去,它一般被用来解决图形面积、周长,以及二维数点等问题。面积问题例题1:【模板】扫描线想象有一条线从下往上扫,会将整个图像依次扫描。我们只需要计算出每一条矩形(即图中同一颜色的小矩......
  • 扫描线模板
    #include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;constintN=1e6+5;//本模板是从左往右扫的,从下往上扫同理#definels(rt<<1)#definers(rt<<1|1)i64cover[N*8];//存放i节点对应区间覆盖情况的值i64n;i64len[N*8];i64yy[N*2];/......
  • 扫描线
    题目链接https://leetcode.cn/problems/rectangle-area-ii/题目大意题目思路选取连续的x值:(left,right),在这个区间内,沿着x轴的方向扫描,求出所有符合条件的(y1,y2)算出扫描区间的h,结合w*h,算出面积!礼貌拿图,多谢三叶姐(https://leetcode.cn/problems/rectangle-area-ii/so......
  • 扫描线的应用1
    概述顾名思义,扫描线通常是在二维空间内,模拟一条线上下扫描,以此达到解决求二维空间的矩形面积或点数问题。实现方法通常采用排序,离散化等操作。排序是为了扫描的不重不漏,而离散化是由于我们模拟的扫描线会一段段扫描,可以去掉重复的信息。 矩形面积1151--Atlantis给定平......
  • 扫描线
    扫描线是什么&矩形面积并本质上可以理解为,对一个二维(或多维)平面上的问题,通过扫描一维,并且用数据结构动态维护另一位的增减性。我们对于\(x\)轴扫描,那么会对面积构成影响的\(y\)显然只有红色的几条和绿色的几条。容易发现,这样的线的数量是\(2n\)的(\(n\)为矩形个数)。......
  • 换维扫描线
    简介一般来说,我们处理某些可以离线的问题,我们会将询问离线,然后将修改挂在左端点或右端点,然后从左往右扫描这些修改,并处理询问,数据结构记录的一般是下标\(i\)到当前走到的地方的一些信息。而换维扫描线则采取了截然相反的措施:我们将区间修改转化成差分,然后从左往右扫描序列,线段......
  • 计算几何——扫描线 学习笔记
    计算几何——扫描线学习笔记你会发现我的笔记的顺序和很多扫描线的讲解是反着来的。其实是和我老师给的课件完全是逆序(谁帮我算一下逆序对啊喵)。前言一开始以为扫描线就是用来求二维几何图像的信息的。但是其实这个并不准确。个人认为,扫描线其实是一个思想,就像动态规划一样......
  • 扫描线学习笔记
    1.引入扫描线多用于图形上,是一条线在图形上扫来扫去,它一般被用来解决图形面积,周长,以及二维数点等问题。2.扫描线求面积并如下图:我们模拟一条扫描线,使它从下往上扫过整个平面,这条扫描线会在遇到横向线段的时候停下来更新一些东西。那么整个图形就可以找出四条线段,如图:更新的......