扫描线模板(离散化版本)

扫描线的思想本质上是通过维护有效长度,切割矩形再进行累加。

如何实现维护有效长度?

假设从左往右扫描,扫到一个矩形的左边时,该矩形的面积开始累加,扫到矩形的右边时,该矩形不再做贡献。

--

以下是废物李一水对该模板的浅薄理解,有错请及时cue我..

 

为什么把pushup写到了update return的地方?

你看,平时放lazytag时是不是update放一遍,query放一遍..

没写query的话,那份下放就一起塞到update里了,保证查询sum[1]时总是对的;

 

为啥不写query,只需要知道sum【1】的值即可,又不想知道其他区间的值;

 

为啥update发现是叶子节点的时候可以直接return不做修改了?

因为叶子节点的爸爸在push的时候把它儿子给改了;

 

 

--

#include<bits/stdc++.h>
using namespace std;
struct lys{
    double up,down,x;
    int inout;
}line[500000];
double sum[500000],cover[900000],yy[500000];
bool cmp(lys a,lys b)
{   if(a.x==b.x) return a.inout>b.inout;
    return a.x<b.x;
}
void push(int rt,int l,int r)
{
    if(cover[rt]>0) sum[rt]=yy[r]-yy[l];
     else if(l+1==r) sum[rt]=0;
     else sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void update(int rt,int l,int r,int ul,int ur,int pd)
{  if(r<ul||l>ur) return;
   if(l>=ul&&r<=ur)
   { 
     cover[rt]+=pd;
        push(rt,l,r);
        return;
   }
       if(l+1==r)
       {
           return;
    }
    int mid=(l+r)>>1;
    if(ul<=mid)
    {
        update(rt<<1,l,mid,ul,ur,pd);
    }
    if(ur>mid)
    {
        update(rt<<1|1,mid,r,ul,ur,pd);
    }
    push(rt,l,r);
}
int main( )
{
    //上左下右边
    //freopen("lys.in","r",stdin);
    int n,k=0;
    while(cin>>n)
    { k++;
        if(n==0) break;
        
        double x,y,x2,y2;
        int cnt=0;
        
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%lf",&x,&y,&x2,&y2);
            cnt++;
            lys u;
            u.x=x;u.up=y2;u.down=y;u.inout=1;
            line[cnt]=u;
            yy[cnt]=y;
            
            cnt++;
            u.x=x2;u.up=y2;u.down=y;u.inout=-1;
            line[cnt]=u;
            yy[cnt]=y2;
        }
        
        sort(line+1,line+cnt+1,cmp);
        sort(yy+1,yy+cnt+1);
        
    
        int len=unique(yy+1,yy+cnt+1)-(yy+1);
        
        memset(sum,0,sizeof(sum));
        memset(cover,0,sizeof(cover));
        
        double ans=0;
        
        for(int i=1;i<=cnt;i++)
        {   //cout<<sum[1]<<" "<<line[i].x<<" "<<line[i-1].x<<endl;
            ans+=sum[1]*(line[i].x-line[i-1].x);
            
            int yl=lower_bound(yy+1,yy+len+1,line[i].down)-yy;
            int yr=lower_bound(yy+1,yy+len+1,line[i].up)-yy;
        //    cout<<yl<<" "<<yr<<endl;
            update(1,1,len,yl,yr,line[i].inout);
            
        }
        
        printf("Test case #%d\n",k);
        printf("Total explored area: %.2lf\n",ans);
        printf("\n");
      } 
}

 

posted @ 2021-10-29 10:09  liyishui  阅读(61)  评论(0编辑  收藏  举报