求\(n\)个矩形的面积并,可以用线段树维护一条垂直于\(y\)轴的直线上被矩形覆盖的长度有多少长,将直线从左往右扫一遍,遇到矩形左边界就+1,遇到右边界就-1,不为\(0\)的位置就表示没有覆盖

不为\(0\)的位置的多少似乎不好维护,

考虑这样一个性质:

如果一个线段树上的区间在扫过一个矩形的左边界被全部覆盖,那么在这个扫过矩形的右边界之前它都是全部被覆盖着的,并且我们每次询问都是询问[1,n]

我们可以在线段树上记录一个\(cnt\)表示一个区间被几个矩形完全覆盖了,如果cnt!=0,那么这个区间的\(ans=r-l\),这样就不需要标记下传了

如果cnt==0,那么用左儿子的ans加上右儿子的ans就可以了

注意线段树左右合并时中间的长度没有计算,所以要用[l,r]的线段树结点维护[l,r+1]的区间

因为数据范围较大,需要离散化

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#define lc p<<1
#define rc p<<1|1
#define mid ((l+r)>>1)
using namespace std; const int MAXN=100010; inline int read(){
int x=0; char c=getchar();
while(c<'0') c=getchar();
while(c>='0') x=x*10+c-'0',c=getchar();
return x;
} struct Matrix{
int x1_,x2_,y1_,y2_;
} a[MAXN]; int n,xx[MAXN<<1],cnt;
int revx[MAXN<<1]; long long Ans; map<int,int> mx; struct Upd{
int yid,l,r,k;
} u[MAXN<<1]; inline bool cmp(Upd p,Upd q){
return p.yid<q.yid;
} int len[MAXN<<4],Cnt[MAXN<<4],numx; inline void push_up(int p,int l,int r){
if(Cnt[p]){
len[p]=revx[r+1]-revx[l];
if(l!=r)
cout<<len[p]<<' '<<len[lc]+len[rc]<<' '<<Cnt[lc]<<' '<<Cnt[rc]<<endl;
}
else len[p]=len[lc]+len[rc];
} inline void update(int L,int R,int d,int p=1,int l=1,int r=numx){
if(L<=l&&r<=R){
Cnt[p]+=d;
push_up(p,l,r);
return;
}
if(L<=mid) update(L,R,d,lc,l,mid);
if(R>mid) update(L,R,d,rc,mid+1,r);
push_up(p,l,r);
} signed main()
{
n=read();
for(int i=1;i<=n;++i){
a[i].x1_=read(),a[i].y1_=read();
a[i].x2_=read(),a[i].y2_=read();
xx[++cnt]=a[i].x1_;
xx[++cnt]=a[i].x2_;
}
sort(xx+1,xx+1+cnt);
for(int i=1;i<=cnt;++i)
if(xx[i]!=xx[i-1])
mx[xx[i]]=++numx,revx[numx]=xx[i];
int unum=0;
for(int i=1;i<=n;++i){
u[++unum].yid=a[i].y1_;
u[unum].l=a[i].x1_;
u[unum].r=a[i].x2_;
u[unum].k=1;
u[++unum].yid=a[i].y2_;
u[unum].l=a[i].x1_;
u[unum].r=a[i].x2_;
u[unum].k=-1;
}
sort(u+1,u+1+unum,cmp);
for(int i=1;i<=unum;++i){
if(i>1&&u[i].yid!=u[i-1].yid){
Ans+=1ll*len[1]*(u[i].yid-u[i-1].yid);
}
update(mx[u[i].l],mx[u[i].r]-1,u[i].k);
}
printf("%lld\n",Ans);
return 0;
}

【luoguP5490】【模板】扫描线的更多相关文章

  1. 线段树基础模板&&扫描线

    线段树的单点更新+区间求和 hdu1166敌兵布阵 Input 第一行一个整数T,表示有T组数据. 每组数据第一行一个正整数N(N<=),表示敌人有N个工兵营地 ,接下来有N个正整数,第i个正整 ...

  2. Atitit 路径规划法attilax总结 扫描线路法

    Atitit 路径规划法attilax总结 扫描线路法 2017/2/8 20:43:37[吐槽]深圳-小 2017/2/8 20:43:37 群主做什么的2017/2/10 10:03:15系统消  ...

  3. 矩形面积并-扫描线 线段树 离散化 模板-poj1151 hdu1542

    今天刚看到这个模板我是懵逼的,这个线段树既没有建树,也没有查询,只有一个update,而且区间成段更新也没有lazy标记....研究了一下午,我突然我发现我以前根本不懂扫描线,之所以没有lazy标记, ...

  4. 覆盖的面积 HDU - 1255 (线段树-扫描线)模板提

    给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1& ...

  5. HDU 1542.Atlantis-线段树求矩形面积并(离散化、扫描线/线段树)-贴模板

    好久没写过博客了,这学期不是很有热情去写博客,写过的题也懒得写题解.现在来水一水博客,写一下若干年前的题目的题解. Atlantis Time Limit: 2000/1000 MS (Java/Ot ...

  6. LA 4127 - The Sky is the Limit (离散化 扫描线 几何模板)

    题目链接 非原创 原创地址:http://blog.csdn.net/jingqi814/article/details/26117241 题意:输入n座山的信息(山的横坐标,高度,山底宽度),计算他 ...

  7. HDU1828 Picture 线段树+扫描线模板题

    Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

  8. [P5490] 【模板】扫描线 - 线段树

    求 \(n\) 个矩形的面积并 Solution 将矩形转化为 \(y_1\) 位置的 + 修改 和 \(y_2\) 位置的 - 修改.然后按照 \(+y\) 顺序依次处理所有的修改,到达的一个新的位 ...

  9. HDU 1542 线段树+扫描线+离散化

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

随机推荐

  1. YAML语言简明教程

    编程免不了要写配置文件,如果你还在用xml/ini/json,就有点过时了,怎么写配置也是一门学问. YAML 是专门用来写配置文件的语言,非常简洁和强大,远比 JSON 格式方便. 本文介绍 YAM ...

  2. chrome安装插件

    看了很多的解决办法,也试了很多种,有的有点用,有的只能用一次,最后成功了,在这里总结一下 一.首先下载 很多人下载的都ctx格式的,然后拖进去安装,用了一次就崩溃了,主要还是安装方式不对,一般需要将下 ...

  3. sklearn中的KMeans算法

    1.聚类算法又叫做“无监督分类”,其目的是将数据划分成有意义或有用的组(或簇).这种划分可以基于我们的业务需求或建模需求来完成,也可以单纯地帮助我们探索数据的自然结构和分布. 2.KMeans算法将一 ...

  4. MongoDB(NoSQL) 非关系型数据库

    目录 简单了解 mongoDB 简单使用mongoDB 简单了解 mongoDB # NoSQL 泛指非关系型的数据库 NoSQL(NoSQL = Not Only SQL ),意即"不仅仅 ...

  5. Microsoft SQL Server 2012安装说明

    Microsoft SQL Server 2012安装说明 环境:Windows8, Windows7, WinVista, Win2003, WinXP Microsoft SQL Server 2 ...

  6. prometheus学习系列十: Prometheus AlertManager配置文件说明

    alertmanager配置文件说明 alertmanager是通过命令行标记和配置文件配置的,命令行标记配置不可变的系统参数,配置文件定义抑制规则.通知路由和通知接收器.可以通过官方提供的routi ...

  7. Flask+SQLAlchemy+graphene+docker示例

    搭建一个利用docker启动服务的Flask的小demo 定义数据库 # -*- coding: utf-8 -*- from sqlalchemy import * from sqlalchemy. ...

  8. 标准库中的装饰器 lru_cache和全新的 singledispatch

    Python 内置了三个用于装饰方法的函数:property.classmethod 和 staticmethod. 另一个常见的装饰器是 functools.wraps,它的作用是协助构建行为 良好 ...

  9. excel 大文件解析原理实现

    问题 目前的excel 不像之前的excel了可以支持的数据量更大,可以支持支持1048576行,16384列. 之前使用poi读取,直接报错,使用excel 事件的方式读取,还有不少的bug,关键是 ...

  10. 提高python处理数据的效率方法

    处理大数据的方法有很多,目前我知道就这么多,后面会持续更新: 一.将数据分批次读取 csv格式是常见的数据存储方式,对于我们普通人而言易于读写.此外,在pandas中有pd.read_csv()函数可 ...