扫描线
本文介绍扫描线的几个题目
二维偏序
E. World of Darkraft: Battle for Azathoth
题意
给定一些武器和防具,每个武器有攻击力,花费,每个防具有防御力和花费
给定一些怪物,每个怪物有攻击力,防御力,价值
你只可以选择一个武器和一个防具,可以获得攻击力小于武器并且防御力小于防具的所有怪物的价值,求最大收益
思路
- 将武器和怪物按照攻击力排序,防具自己排序,并且按照防具的防御力防具顺序(id)建立下标线段树
- 双指针i指向武器,j指向怪物,当i指针向右边移动1个,j指针只会向右边移动,且以后的i一定可以选到当前的怪物j,所以当前的j造成的贡献会一直保留。所以将j的贡献加到线段树中即可
- 对于每一个武器i算最大价值,详细见代码
代码
1 | |
E. Number of Groups
题意
给一些线段[x,y],每个线段有一个颜色(0或者1),如果两个不同颜色的线段有交集,那他们在同一组,问有多少不同的组
思路
- 将一个线段的x,y看成时间(time),将插入和删除看成时间(event),显然,一个线段的x是插入,y是删除,这是典型的扫描线想法
- 按照(time,event)排序,对于插入操作,我们需要知道可以和哪些线段合并,同时自己要记录自己在那个集合中
- 显然并查集
步骤
- 开两个集合,存每种颜色的线段右端点即可
- 按照(time,event)排序后,遍历所有点对,如果是插入操作,查询谁跟他一组,暴力合并,如果是删除操作,删除这个点对即可。但是此时会超时,因为每个线段都可以被合并很多次,复杂度不可以保证。
- 考虑贪心,若两个0颜色线段在同一个集合中,此时他们肯定都没有删除,此时遍历到第i个点对,那么,如果是插入操作,此时只需要和最后一个合并即可(如果可以的话),因为合并的前提是当前点对的time,也就是
另一个线段的左端点<=一个线段的左端点要<=另一个线段的右端点,所以贪心即可,边合并边删除即可,具体看代码
1 | |
P4137 Rmq Problem / mex
题意
给定一个序列,多次询问,区间mex是多少
思路
- 莫队秒了
- 权值线段树扫描线,扫描序列,到达第i个位置的时候,处理以第i个位置为右端点的所有询问。转化为求最小的x,满足$pos[x]<l$,x就是第id个询问的答案,显然可以用线段树二分。
- 只需要将权值x当成下标就可以,支持更新pos[x],和区间查询即可
- 注意权值从0开始
代码
莫队
1 | |
权值线段树
1 | |
扫描线
http://example.com/2023/12/01/算法/扫描线/