关于扫描线的一些理解
2015-12-27 16:46
225 查看
关于扫描线这个东西,其实是不太好开始学习的,因为百度到的东西大部分是比较高深,或者是和计算几何相关的东西。
感觉稍微写点自己的理解吧……
一、关于扫描线
关于扫描线这个东西,其实就和我们脑海中想象的是一样的,一根线在要进行的区间上进行“扫描”。
扫到的地方就在线上进行某些性质的改变。
所以扫描线更像是一种思想,而不是某些特定的算法。
二、扫描线的初级实现
拿一道例题来看。
Codeforces Educational Rouund #4 D
题意是 以Li,Ri的形式给出一些线段,让你求出恰好被覆盖了k次的区间。
我们在脑内脑补一下。
假设有一条竖直线,从左到右的把整个区间扫描了一遍。
每次遇到一个左端点,覆盖数+1,遇到一个右端点,覆盖数-1。
我们称“覆盖数的变化”为 “事件”。
在这道题里,一条线段对应的是两个事件。
我们定义一个event,记录下每条线段的L和时间的种类——即“入”或“出”。
将“入”记为+1,“出”为-1是比较容易理解的。
在这道题里我们可以发现,事件的发生顺序是由L决定的,所以我们按照L的升序将线段排序。
然后在扫描的过程中我们就可以得到 当覆盖数为k时的区间。
复杂度 O(nlogn) n为事件数(本题事件数为线段数*2)。
三、扫描线的中级实现
上面说到扫描线经常可以和一些面积问题相结合,还可以使用某些数据结构来维护。
比如POJ 1151这个题就是利用了线段树来维护“事件”。
(未完待补)
感觉稍微写点自己的理解吧……
一、关于扫描线
关于扫描线这个东西,其实就和我们脑海中想象的是一样的,一根线在要进行的区间上进行“扫描”。
扫到的地方就在线上进行某些性质的改变。
所以扫描线更像是一种思想,而不是某些特定的算法。
二、扫描线的初级实现
拿一道例题来看。
Codeforces Educational Rouund #4 D
题意是 以Li,Ri的形式给出一些线段,让你求出恰好被覆盖了k次的区间。
我们在脑内脑补一下。
假设有一条竖直线,从左到右的把整个区间扫描了一遍。
每次遇到一个左端点,覆盖数+1,遇到一个右端点,覆盖数-1。
我们称“覆盖数的变化”为 “事件”。
在这道题里,一条线段对应的是两个事件。
我们定义一个event,记录下每条线段的L和时间的种类——即“入”或“出”。
将“入”记为+1,“出”为-1是比较容易理解的。
在这道题里我们可以发现,事件的发生顺序是由L决定的,所以我们按照L的升序将线段排序。
然后在扫描的过程中我们就可以得到 当覆盖数为k时的区间。
复杂度 O(nlogn) n为事件数(本题事件数为线段数*2)。
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> #include<queue> #include<vector> #include<set> #include<stack> #include<map> #include<ctime> #include<bitset> #define LL long long #define db double #define EPS 1e-15 #define inf 1e10 using namespace std; int main(){ LL n,k,a,b,cur=0; scanf("%I64d%I64d",&n,&k); vector<pair<LL,LL> > event; vector<LL> ans; for (LL i=0;i<n;i++) { scanf("%I64d%I64d",&a,&b); event.push_back(make_pair(a,-1)); event.push_back(make_pair(b,1)); } sort(event.begin(),event.end()); int cnt=0; for (LL x=0;x<event.size();x++){ if (event[x].second==1){ if (cnt==k) ans.push_back(event[x].first); cnt--; } else { cnt++; if (cnt==k) ans.push_back(event[x].first); } } printf("%d\n",ans.size()/2); for (int x=0;x<ans.size()/2;x++) printf("%I64d %I64d\n", ans[x*2],ans[x*2+1]); return 0; }
三、扫描线的中级实现
上面说到扫描线经常可以和一些面积问题相结合,还可以使用某些数据结构来维护。
比如POJ 1151这个题就是利用了线段树来维护“事件”。
(未完待补)
相关文章推荐
- 【C++】深度探索C++对象模型之站在对象模型的顶端
- 自动化管理工具Saltstack之服务管理(10)
- 扣丁学堂——XML解析
- print_r、echo、var_dump三者的区别
- print_r、echo、var_dump三者的区别
- Gzip
- 线性表
- 读取文件夹下的所有文件
- Oracle日常维护中管理用户以及重做日志文件的方法
- 23种设计模式(22)_行为型_责任链模式(Chain of Responsibility Pattern)
- url转换
- ios app 上架AppStore
- JavaScrip——练习(做悬浮框进一步:悬浮窗后缀悬浮窗【感觉这种方法比较麻烦】)
- js事件3-事件对象
- 大脑视觉处理~~
- SNMP 协议工作原理验证与分析
- python学习——基础(四)
- js事件3-事件对象
- libev的安装
- 自动化管理工具Saltstack之定时管理(9)