扫描线入门
来源:互联网 发布:centos 光盘 yum源 编辑:程序博客网 时间:2024/05/21 17:27
听说扫描线很牛掰,于是就见识了一下。
之前做过一道扫描线的题,brother,就是判断矩形是否被矩形内部的车攻击到。当时是把矩形拆成出边和入边(竖直的),把所有小于x2的车加进图中,扫[y1,y2]中x最小的车的x.和x1判断比较。然后交换x,y扫一遍
当时只是感觉线段树很神奇,还可以这样搞,后来才知道这种按x2的排序遍历就相当于扫描线。
然后就做了扫描线的入门题。
Weird Advertisement
UVA - 11983一道扫描线矩形面积并,求被覆盖k次的矩形面积(虽然是点,不过x2+1,y2+1就变成了求面积。 比如只有一个点,把它x2+1,y2+1,就变成了面积为1的正方形)。
理解了大致思路,套了个版.
下面解决一下大致思路吧。
把矩形拆成入边和出边,记录下来,还要打上出入边标记。
按x排序(我是按x拆的,两条边x不同,竖直),然后扫到入边,把[y1,y2]加入,否则把[y1,y2]减去。
要更新>=k的次数。
其实主要复杂一点的是pushup.
一般需要离散化,因为题目往往不会很简单
覆盖K次矩形面积并
#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<algorithm>#include<queue>#include<cmath>#define LL long longusing namespace std;LL n,k;const LL maxn=30000+20;struct line{LL x,y1,y2,flag;line(LL x,LL y1,LL y2,LL flag){this->x=x;this->y1=y1;this->y2=y2;this->flag=flag;}bool operator<(const line &p)const{return x<p.x;}};vector<line>L;LL det[maxn*2];LL tot=0;LL find(LL x){return lower_bound(det+1,det+tot+1,x)-det;}struct node{LL l,r,flag;LL len[12];//长度为k的有多少个 void set(LL l,LL r,LL flag){this->l=l;this->r=r;this->flag=flag;}}T[8*maxn];void pushup(LL u){LL l=T[u].l;LL r=T[u].r;for(LL i=0;i<=k;i++)T[u].len[i]=0;if(l==r){LL t=min(T[u].flag,k);T[u].len[t]=det[r+1]-det[l];}else{for(LL i=0;i<=k;i++){LL t=min(T[u].flag+i,k);T[u].len[t]+=T[u<<1].len[i]+T[u<<1|1].len[i];}}}void build(LL i,LL l,LL r){T[i].set(l,r,0);if(l==r){pushup(i);return ;}LL mid=(l+r)>>1;build(i<<1,l,mid);build(i<<1|1,mid+1,r);pushup(i);}void updata(LL i,LL L,LL R,LL x){LL l=T[i].l;LL r=T[i].r;if(l>=L&&r<=R){T[i].flag+=x;pushup(i);return ;}LL mid=(l+r)>>1;if(L<=mid)updata(i<<1,L,R,x);if(R>mid)updata(i<<1|1,L,R,x);pushup(i);}int main(){LL yu;scanf("%lld",&yu);for(LL cas=1;cas<=yu;cas++){tot=0;L.clear();scanf("%lld%lld",&n,&k);for(LL i=1;i<=n;i++){LL x1,y1,x2,y2;scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);det[++tot]=y1;det[++tot]=y2+1;L.push_back(line(x1,y1,y2+1,1));L.push_back(line(x2+1,y1,y2+1,-1));}sort(L.begin(),L.end()); sort(det+1,det+tot+1); LL t=tot; tot=unique(det+1,det+t+1)-det-1; build(1,1,tot); LL ans=0; for(LL i=0;i<L.size()-1;i++) { LL l=find(L[i].y1); LL r=find(L[i].y2); updata(1,l,r-1,L[i].flag); ans+=(L[i+1].x-L[i].x)*T[1].len[k]; } printf("Case %lld: %lld\n",cas,ans);}return 0;}
这是最裸的矩形面积并。
#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<algorithm>#include<queue>#include<cmath>#include<vector>#define LL long longusing namespace std;LL n;const LL maxn=100000+20;const LL k=1;struct line{LL x,y1,y2,flag;line(LL x,LL y1,LL y2,LL flag){this->x=x;this->y1=y1;this->y2=y2;this->flag=flag;}bool operator<(const line&p)const{return x<p.x;}};vector<line>L;LL det[maxn*2];LL tot;LL find(LL x){return lower_bound(det+1,det+tot+1,x)-det;}struct node{LL l,r,flag;LL len[5];void set(LL l,LL r,LL flag){this->l=l;this->r=r;this->flag=flag;}}T[8*maxn];void pushup(LL i){LL l=T[i].l;LL r=T[i].r;for(LL j=0;j<=k;j++)T[i].len[j]=0;if(l==r){LL t=min(T[i].flag,k);T[i].len[t]=det[l+1]-det[l];}else {for(LL j=0;j<=k;j++){LL t=min(T[i].flag+j,k);T[i].len[t]+=T[i<<1].len[j]+T[i<<1|1].len[j];}}}void build(LL i,LL l,LL r){T[i].set(l,r,0);if(l==r){pushup(i);return ;}LL mid=(l+r)>>1;build(i<<1,l,mid);build(i<<1|1,mid+1,r);pushup(i);}void updata(LL i,LL L,LL R,LL x){LL l=T[i].l;LL r=T[i].r;if(l>=L&&r<=R){T[i].flag+=x;pushup(i);return ;}LL mid=(l+r)>>1;if(L<=mid)updata(i<<1,L,R,x);if(R>mid)updata(i<<1|1,L,R,x);pushup(i);}int main(){freopen("rectangle.in","r",stdin);freopen("rectangle.out","w",stdout);tot=0;scanf("%I64d",&n);for(LL i=1;i<=n;i++){ LL x1,y1,x2,y2;scanf("%I64d%I64d%I64d%I64d",&x1,&y1,&x2,&y2);L.push_back(line(x1,y1,y2,1));L.push_back(line(x2,y1,y2,-1));det[++tot]=y1;det[++tot]=y2;}sort(det+1,det+tot+1);sort(L.begin(),L.end());LL t=tot;tot=unique(det+1,det+t+1)-det-1;build(1,1,tot);LL ans=0;for(LL i=0;i<L.size()-1;i++){LL l=find(L[i].y1);LL r=find(L[i].y2);updata(1,l,r-1,L[i].flag);ans+=T[1].len[1]*(L[i+1].x-L[i].x);}printf("%I64d\n",ans);return 0;}
扫描线大致是一种思想,用数据结构维护。
3 0
- 扫描线入门
- 三维激光扫描技术入门
- 扫描线
- 扫描线
- 扫描线
- 扫描线
- 扫描线
- 扫描线
- 扫描探针显微术入门(1)
- 【菜鸟入门】stm32 之 扫描按键
- 扫描探针显微术入门(3)
- 扫描探针显微术入门(4)
- 扫描探针显微术入门(5)
- 扫描探针显微术入门(6)
- 扫描探针显微术入门(7)
- 多边形扫描线算法
- HDU 4007 线扫描
- 线段树[扫描线]
- uart 编程
- Maven简明教程(3)---在eclipse中创建工程与基本命令介绍
- 开源 java CMS - FreeCMS2.4 系统配置
- Linux 标准库下的unistd.h
- 关于修改nginx中的cahce的key的生成规则的思考
- 扫描线入门
- 记第一次投标 --- 失败
- webService、servlet和RMI的区别
- 使用Apache Directory Studio初始化Cordys BOP CARS
- PHP二维数组排序
- Core Foundation 与 cocoa Foundation框架区别
- 在Eclipse下package和source Folder 和folder的区别以及相互转换
- C/C++刁钻问题各个击破之细说sizeof
- tomcat7链接mysql