————出自南昌理工学院ACM集训队

这周学习了线段树和扫描线的解题方法,下面由小菜鸡简介一下:
一般扫描线的题目最简单的便是扫描线裸模板(一般来说的话:数据范围小),其次的话便是进行拓展成线段树+扫描线(数据范围增大),再难一点的话就是扫描线+线段树+加上离散化操作了。

扫描线

什么是扫描线呢:
给你一堆的矩形求这些矩形再重叠的情况下的面积?便需要用到扫描线

按照x排序从小到大 xi(1~8),这样处理之后我们可以看到 每两的相邻的 xi的值把矩形分成了若干个矩形,这是我们记录一下上面的长y2和下面的长y1。总的面积的答案ans+=(x2-x1)*(y2-y1)加上每两个xi之前并且属于题目矩形 ,这里面还涉及一个区间合并(例如x2到x3所形成的矩阵)。

扫描线+线段树
例题:油漆面积
X星球的一批考古机器人正在一片废墟上考古。
该区域的地面坚硬如石、平整如镜。
管理人员为方便,建立了标准的直角坐标系。
每个机器人都各有特长、身怀绝技。
它们感兴趣的内容也不相同。
经过各种测量,每个机器人都会报告一个或多个矩形区域,作为优先考古的区域。
矩形的表示格式为 (x1,y1,x2,y2),代表矩形的两个对角点坐标。
为了醒目,总部要求对所有机器人选中的矩形区域涂黄色油漆。
小明并不需要当油漆工,只是他需要计算一下,一共要耗费多少油漆。
其实这也不难,只要算出所有矩形覆盖的区域一共有多大面积就可以了。
注意,各个矩形间可能重叠。

输入格式
第一行,一个整数 n,表示有多少个矩形。
接下来的 n 行,每行有 4 个整数 x1,y1,x2,y2,空格分开,表示矩形的两个对角顶点坐标。
输出格式
一行一个整数,表示矩形覆盖的总面积。
数据范围
1≤n≤10000,
0≤x1,x2,y2,y2≤10000
数据保证 x1<x2 且 y1<y2。
输入样例:
3
5 2 10 6
2 7 12 10
8 1 15 15
输出
128

需要结构体保存四元组(x,y1,y2,k)x代表这条边算在x轴的位子,y1、y2代表这条边在x的下限和上限。k表示标记。

 #include<bits/stdc++.h>using namespace std;typedef long long ll;const int N=10100;//数据范围int ls(int x){//左节点return x<<1;} int rs(int x){//右节点return x<<1|1;}struct node{int x,y1,y2;//x代表这条边算在x轴的位子,y1、y2代表这条边在x的下限和上限int k;//k表示标记。}seg[N*2];//一个矩阵有两条平行于y轴的边,所以要乘2struct Node{int l,r;int cnt,len;}; Node tree[N*4];//建树的存储大小int n;void build(int l,int r,int u){//建线段树tree[u]={l,r};if(r==l)return ;int mid=(l+r)>>1;build(l,mid,ls(u));build(mid+1,r,rs(u));}void push_up(int p){//向上更新if(tree[p].cnt>0){tree[p].len=tree[p].r-tree[p].l+1;}else if(tree[p].l==tree[p].r) tree[p].len=0;else tree[p].len=(tree[ls(p)].len+tree[rs(p)].len);}
bool cmp(node a,node b){return a.x<b.x;
}
void modify(int u,int l,int r,int k){//更新每一条平行于Y轴的边if(tree[u].l>=l&&tree[u].r<=r){tree[u].cnt+=k;push_up(u);}else{int mid=(tree[u].r+tree[u].l)>>1;if(mid>=l){modify(ls(u),l,r,k);}if(mid<r){modify(rs(u),l,r,k);}push_up(u);}
}int main(){cin>>n;int m=0;for(int i=1;i<=n;i++){int x1,x2,y1,y2;cin>>x1>>y1>>x2>>y2;seg[m++]={x1,y1,y2,1};//每一次先存正标记seg[m++]={x2,y1,y2,-1};}sort(seg,seg+m,cmp); //按x大小从小到大排完序之后还是正标记在前(指的是同一矩阵的两条边)build(0,10000,1);int ans=0;for(int i = 0; i < m; i ++){if(i>0) ans+=tree[1].len*(seg[i].x-seg[i-1].x);//每一次加的是相邻的两个xi之间并且在矩形中的部分。modify(1,seg[i].y1,seg[i].y2-1,seg[i].k);}cout<<ans<<endl;return 0;}

离散化:

vector<int> mp;
for(int i=0;i<=n;i++)
mp.push_back(a[i]);
sort(mp.begin().mp.end());
mp.erase(unique(mp.begin(),mp.end()),mp.end());

线段树+扫描线+离散化

离散化:坐标大就离散化
二分:离散化就二分
扫描线:数据范围大,又是二维,还是要扫描线
线段树:数据范围大,区间可加性,一堆区间操作,还是要线段树

例题:AcWing248窗内的星星
在一个天空中有很多星星(看作平面直角坐标系),已知每颗星星的坐标和亮度(都是整数)。
求用宽为 W、高为 H 的矩形窗口(W,H 为正整数)能圈住的星星的亮度总和最大是多少。(矩形边界上的星星不算)

输入格式
输入包含多组测试用例。
每个用例的第一行包含 3 个整数:n,W,H,表示星星的数量,矩形窗口的宽和高。然后是 n 行,每行有 3 个整数:x,y,c,表示每个星星的位置 (x,y) 和亮度。没有两颗星星在同一点上。

输出格式
每个测试用例输出一个亮度总和最大值。

每个结果占一行。

数据范围
1≤n≤10000,
1≤W,H≤1000000,
0≤x,y<231
输入样例:
3 5 4
1 2 3
2 3 2
6 3 1
3 5 4
1 2 3
2 3 2
5 3 1
将问题转化为:平面上由若干个区域,每个区域都带有一个权值,求在哪个坐标上重叠的区域权值和最大.记住,每一个区域都是有一个星星产生的,权值等于星星的亮度.这里要注意在这个长为W 高为H的矩阵的边界上的星星不算所以等会建树的时候要注意。

 #include<bits/stdc++.h>using namespace std;typedef long long ll;const int N=10100;vector<ll> mp;int ls(int x){return x<<1;} int rs(int x){return x<<1|1;}struct node{ll x,y1,y2;ll k;}seg[N*2];struct Node{ll l,r;ll cnt,len;}; Node tree[N*8];ll n;void build(ll l,ll r,ll u){tree[u]={mp[l],mp[r],0,0};if(r - l == 1)//考虑到相邻的不能要。return ;ll mid=(l+r)>>1;build(l,mid,ls(u));build(mid,r,rs(u));}
void  push_up(ll p){tree[p].len=max(tree[rs(p)].len,tree[ls(p)].len)+tree[p].cnt;}
bool cmp(node a,node b){return a.x<b.x|| (a.x==b.x && a.k<0);
}
void modify(ll u,ll l,ll r,ll k){if(tree[u].l>=l&&tree[u].r<=r){tree[u].cnt+=k;tree[u].len+=k; return ;}ll mid=l+r>>1;if(l<tree[ls(u)].r){modify(ls(u),l,min(r,tree[ls(u)].r),k);}if(r>tree[rs(u)].l){modify(rs(u),max(l,tree[rs(u)].l),r,k);}push_up(u);
}int main(){ll n,h,w;while(cin>>n>>w>>h){ll m=0;for(int i=1;i<=n;i++){ll x,y,k;cin>>x>>y>>k;seg[m++]={x,y,y+h,k};seg[m++]={x+w,y,y+h,-k};mp.push_back(y);mp.push_back(y+h);}sort(seg,seg+m,cmp); sort(mp.begin(),mp.end());mp.erase(unique(mp.begin(),mp.end()),mp.end());build(0,mp.size()-1,1);ll ans=0;for(int i = 0; i < m; i ++){int tmp=lower_bound(mp.begin(),mp.end(),seg[i].y1)-mp.begin();int tmp1=lower_bound(mp.begin(),mp.end(),seg[i].y2)-mp.begin();modify(1,mp[tmp],mp[tmp1],seg[i].k);if(seg[i].k>0)ans=max(ans,tree[1].len);}cout<<ans<<endl;}return 0;} ```

扫描线+线段树简介 AcWing 248窗内的星星题解相关推荐

  1. AcWing 248. 窗内的星星

    '两个囚犯从监狱的窗子里向外看,一个凝视着泥土,一个仰望着星空' #include <bits/stdc++.h> // #define LOCAL #define INF 0xf3f3f ...

  2. 【HDU5091】Beam Cannon,扫描线+线段树

    传送门 思路: 扫描线的经典问题 然而并不是很会做-- 对x坐标差分一下(例如(x,y)类型为1,(x+w,y)的类型就是-1,以便于之后扫描可以去除该点),然后对y坐标转化为正数(便于操作为线段树上 ...

  3. 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树

    [BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...

  4. [矩形并-扫描线-线段树]Picture

    最近在补数学和几何,没啥好写的,因为已经决定每天至少写一篇了,今天随便拿个题水水. 题目大意:给你N个边平行于坐标轴的矩形,求它们并的周长.(N<=5000) 思路:这个数据范围瞎暴力就过了,但 ...

  5. [BZOJ4422][Cerc2015]Cow Confinement(扫描线+线段树)

    === === 这里放传送门 === === 题解 记得这题很久以前学长出过胡策..然后当时没做出来..然后照着题解打了一发然后怎么调怎么WA然后就弃了..当时的题解好像是用差分什么的?基本思路是对每 ...

  6. POJ 1177 Picture [离散化+扫描线+线段树]

    http://poj.org/problem?id=1177 给若干矩形,求被覆盖的区域的周长. 将 y 坐标离散化后,按 x 坐标进行扫描.用线段树维护两个东西,当前竖线的叠加长度 len 和 条数 ...

  7. HDOJ 3642 Get The Treasury(扫描线 + 线段树 + 离散化 立方体的并)

    题意: 给一些长方体,求这些长方体相交至少3次的体积的并. 思路: 1. 先注意到 z 的变化范围 0 - 500,于是可以先把 z 离散化再枚举 z 坐标的高度. 2. 对于每一个 z[i] - z ...

  8. hdu 4419 Colourful Rectangle (离散化扫描线线段树)

    Problem - 4419 题意不难,红绿蓝三种颜色覆盖在平面上,不同颜色的区域相交会产生新的颜色,求每一种颜色的面积大小. 比较明显,这题要从矩形面积并的方向出发.如果做过矩形面积并的题,用线段树 ...

  9. 清明梦超能力者黄YY[树链剖分+扫描线,线段树合并]

    清明梦超能力者黄YY 题目连接 https://www.nowcoder.com/acm/contest/206/I 暂时有两种做法. 算法一 涉及:树链剖分,扫描线 在一个线段的情况下,我们可以把一 ...

最新文章

  1. WPF一步一脚印系列(1):万事起头难
  2. android的窗口机制分析------ViewRoot类
  3. 不可达的对象一定要被回收吗?
  4. 读书笔记 - 《乌合之众》
  5. 各科老师的语言风格一览,太真实了哈哈哈哈哈哈
  6. 带用户名和密码的GitHub链接
  7. C语言给考场编号,求:用C设计考场的编排,生成准考证号基本要求:br/(1)用 爱问知识人...
  8. 福建工程学院计算机专利,基于车床硬件平台的再制造数控滚齿机专利_专利查询 - 天眼查...
  9. 拓端tecdat|主成分分析(PCA)原理及R语言实现及分析实例
  10. Git的学习笔记(一)
  11. matlab识别水雷岩石,基于MATLAB的微弱信号检测方法仿真分析
  12. Android本地音乐播放器
  13. 20162327WJH 实验三 《敏捷开发与XP实践》 实验报告
  14. XV6操作系统make报错Makefile:192: *** recipe commences before first target. Stop. 的解决方法
  15. 作为一个男人,必须在30岁前做到这16件事
  16. NewTek LightWave 3D 2018 破解版
  17. 我们分析了金庸小说中出现的1367个人物名字,发现了一些相当惊人的事情
  18. 一文带你重新审视CAP理论与分布式系统设计
  19. 小巧的本地缓存Jodd
  20. html静态商城网页制作 基于HTML+CSS+JavaScript在线服装商城店铺商城设计毕业论文源码

热门文章

  1. 《炬丰科技-半导体工艺》湿法刻蚀硅片表面性能的变化
  2. Ansys workbench 云图如何不显示边框
  3. Java-jdk下载 (jdk1.6,jdk1.7,jdk1.8,jdk1.9,... 各个版本镜像下载)
  4. xp系统无法从补丁服务器获取补丁,WindowsXP系统依然能获取微软补丁的小技巧
  5. IP 地址 与 DNS
  6. PHP教程smarty学习指南
  7. 【鲁棒优化、大M法、CCG算法】计及风、光、负荷不确定性两阶段鲁棒优化(Matlab代码实现)
  8. 如何使用js实现电影海报画廊特效?
  9. WebGL停车场三维可视化管理系统 DEMO(ThingJS 停车场3D可视化管理)
  10. GET https://pic.qyer.com/avatar/008/23/22/84/200?v=1469960206 403 (Forbidden) 图片防盗链