扫描线练习笔记

之前并不能理解扫描线这种东西,真的以为是条线,还在想这玩意到底要怎么实现?

结果理解后,好像还真是条线。

好吧。其实是以一个坐标轴的点确定的直线+长度,直线和长度便确定了线段,也有了值。

扫描线应该说是靠顺序查询轴线点来实现的。

看了一个大佬的博客,受益匪浅。我是看了这个博客才明白扫描线这东西的做法。

然后根据那个博客,我改了里边的代码,做了我扫描线的第一题,洛谷的P1904

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e4+50;
int mark[maxn<<2];//记录某个区间的下底边个数
int sum[maxn<<2];//记录某个区间的下底边总长度
int a[maxn];//对h进行离散化
//以纵坐标作为线段(区间),对纵坐标线段进行扫描 
struct P{
    int x,h,ju;//以h为扫描线平行边,x为扫描方向,ju=-1为左 ju=1为右
    bool operator <(const P&p)const{return x<p.x;}
    P(){}
    P(int xx,int hh,int juu){x=xx;h=hh;ju=juu;}
}s[maxn];
void upfather(int k,int l,int r){
    if(mark[k])sum[k]=a[r+1]-a[l];//
    else if(l==r)sum[k]=0;
    else sum[k]=sum[k<<1]+sum[k<<1|1];
}//n k
void update(int L,int R,int ju,int k,int l,int r){
    if(L<=l&&r<=R){
        mark[k]+=ju;
        upfather(k,l,r);
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid)update(L,R,ju,k<<1,l,mid);
    if(R>mid)update(L,R,ju,k<<1|1,mid+1,r);
    upfather(k,l,r);
}
int search(int key,int *x,int k){
    int l=0,r=k-1;
    while(l<=r){
        int mid=(l+r)>>1;
        if(x[mid]==key)return mid;
        if(x[mid]>key)r=mid-1;
        else l=mid+1; 
    }
    return -1;
}
struct PP{
    int x,y;
    PP(){}
    PP(int xx,int yy){x=xx;y=yy;}
}ans[maxn<<2];
int solve(int tot,int up)//tot是边数 up是点数 
{
    int upp=0,tans=0;
    for(int i=0;i<tot;i++){
        int R=search(s[i].h,a,up)-1;
        update(0,R,s[i].ju,1,0,up-1);//printf("!");
        if(sum[1]==tans)continue;
        if(ans[upp-1].x==s[i].x&&ans[upp-1].y==tans)upp--;
        else ans[upp++]=PP(s[i].x,tans);
        if(ans[upp-1].x==s[i].x&&ans[upp-1].y==sum[1])upp--;
        else ans[upp++]=PP(s[i].x,sum[1]);
        tans=sum[1];
    }
    return upp;
}
int main()
{
    int n,tot=0,l,h,r,up=0;
    a[up++]=0;
//    scanf("%d",&n);
    while(~scanf("%d%d%d",&l,&h,&r))
//    while(tot<n*2)
    {
//        scanf("%d%d%d",&l,&h,&r);
        a[up++]=h;
        s[tot++]=P(l,h,-1);
        s[tot++]=P(r,h,1);
    }
    sort(a,a+up);
    sort(s,s+tot);
    up=unique(a,a+up)-a;
    int upp=solve(tot,up);
    for(int i=0;i<upp;i++)
    {
        if(i&1)printf("%d ",ans[i].y);
        else printf("%d ",ans[i].x);
//         printf("%d% d\n",ans[i].x,ans[i].y);
    }
}

2019-09-04

猜你喜欢

转载自www.cnblogs.com/kkkek/p/11462426.html