[题解/模板]扫描线

Posted superminivan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[题解/模板]扫描线相关的知识,希望对你有一定的参考价值。

luogu_P1856矩形周长

#include<bits/stdc++.h>
#define ls (x<<1)
#define rs (x<<1|1)
//#define mid (l+r>>1)
using namespace std;
const int maxn=5009;
const int maxm=10009;
int n,ans;
struct square
    int xa,xb,ya,yb;
r[maxn];
int hsh[maxn<<1],cnt;
struct line
    int l,r,h,f;
    bool operator <(const line&a)const
        return h<a.h||h==a.h &&f>a.f;
    
e[maxn<<1];
struct node
    int sum,tag;
t[maxm<<2];
void upd(int x,int l,int r)
    if(t[x].tag)t[x].sum=hsh[r+1]-hsh[l];
    else if(l==r)t[x].sum=0;
    else t[x].sum=t[ls].sum+t[rs].sum;

void change(int x,int l,int r,int L,int R,int f)
    if(L<=l && r<=R)
        t[x].tag+=f;
        
    
    else
        int mid=(l+r)>>1;
        if(L<=mid)change(ls,l,mid,L,R,f);
        if(R>mid)change(rs,mid+1,r,L,R,f);
    
    upd(x,l,r);

//int find(int x,int l,int r)
//    while(l<=r)
//        int mid=l+r>>1;
//        if(hsh[mid]<x)l=mid+1;
//        else if(hsh[mid]==x)return mid;
//        else r=mid-1;
//    
//
int solve()
    int res=0;
    sort(hsh+1,hsh+1+cnt);
    sort(e+1,e+1+cnt);
    for(int i=1;i<=cnt;i++)
        int l=lower_bound(hsh+1,hsh+1+cnt,e[i].l)-hsh,
        r=lower_bound(hsh+1,hsh+1+cnt,e[i].r)-hsh-1;//这里要减一线段树维护的长度才正确 
//        int l=find(e[i].l,1,cnt),r=find(e[i].r,1,cnt)-1;
        if(l<=r)
            int lst=t[1].sum;
            change(1,1,cnt,l,r,e[i].f);
            res+=abs(t[1].sum-lst);
        
    
    return res;

int main()
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d%d%d",&r[i].xa,&r[i].ya,&r[i].xb,&r[i].yb);
        hsh[++cnt]=r[i].xa;e[cnt].l=r[i].xa;
        e[cnt].r=r[i].xb;e[cnt].h=r[i].ya;e[cnt].f=1;
        hsh[++cnt]=r[i].xb;e[cnt].l=r[i].xa;
        e[cnt].r=r[i].xb,e[cnt].h=r[i].yb,e[cnt].f=-1;
    
    ans+=solve();
    cnt=0;
    for(int i=1;i<=n;i++)
        hsh[++cnt]=r[i].ya,e[cnt].l=r[i].ya;
        e[cnt].r=r[i].yb,e[cnt].h=r[i].xa,e[cnt].f=1;
        hsh[++cnt]=r[i].yb,e[cnt].l=r[i].ya;
        e[cnt].r=r[i].yb,e[cnt].h=r[i].xb,e[cnt].f=-1;
    
    ans+=solve();
    printf("%d",ans);

POJ_1151_Atlantis

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ls (x<<1)
#define rs (x<<1|1)
#define ll long long
using namespace std;
const int maxn=509;
int n;
double ans;
struct node
    double xa,xb,ya,yb;
r[maxn];
double hsh[maxn<<1];int cnt;
struct line
    double l,r,h;
    int f;
    bool operator <(const line &a)const
        return h<a.h || h==a.h && f>a.f;
    
e[maxn<<1];
struct tree
    double sum;
    int tag;
t[maxn<<2];
void upd(int x,int l,int r)
    if(t[x].tag)t[x].sum=hsh[r+1]-hsh[l];
    else if(l==r)t[x].sum=0;
    else t[x].sum=t[ls].sum+t[rs].sum;

void change(int x,int l,int r,int L,int R,int f)
    if(L<=l && r<=R)
        t[x].tag+=f;
    
    else
        int mid=l+r>>1;
        if(L<=mid)change(ls,l,mid,L,R,f);
        if(R>mid)change(rs,mid+1,r,L,R,f);
    
    upd(x,l,r);

double solve()
    double res=0;
    sort(hsh+1,hsh+1+cnt);
    sort(e+1,e+1+cnt);
    int tot=unique(hsh+1,hsh+1+cnt)-hsh-1;
    for(int i=1;i<cnt;i++)
        int l=lower_bound(hsh+1,hsh+1+tot,e[i].l)-hsh,
        r=lower_bound(hsh+1,hsh+1+tot,e[i].r)-hsh-1;
        if(l<=r)    
            change(1,1,tot,l,r,e[i].f);
        res+=fabs(t[1].sum)*(e[i+1].h-e[i].h);
    
    return res;

int main()int tt=0;
    while(scanf("%d",&n) && n)tt++;
        cnt=0;
        memset(hsh,0,sizeof(hsh));
        memset(t,0,sizeof(t));
        for(int i=1;i<=n;i++)
            scanf("%lf%lf%lf%lf",&r[i].xa,&r[i].ya,&r[i].xb,&r[i].yb);
            hsh[++cnt]=r[i].xa;
            e[cnt].l=r[i].xa;
            e[cnt].r=r[i].xb;
            e[cnt].h=r[i].ya;
            e[cnt].f=1;
            hsh[++cnt]=r[i].xb;
            e[cnt].l=r[i].xa;
            e[cnt].r=r[i].xb;
            e[cnt].h=r[i].yb;
            e[cnt].f=-1;
        
        printf("Test case #%d\n",tt);
        printf("Total explored area: %.2f\n\n",solve());
    

 

以上是关于[题解/模板]扫描线的主要内容,如果未能解决你的问题,请参考以下文章

Luogu5816 内部白点(扫描线)题解

HDU - 5770 Treasure 思维 + 扫描线 + 线段树 (看题解)

Gym 100733J Summer Wars 题解:灵活运用扫描线的思想

poj1389:Area of Simple Polygons——扫描线线段树题解+全套代码注释

luogu_P5490 模板扫描线

扫描线模板