【POJ1151】Atlantis

【题意】矩形面积求并

【分析】这是扫描线最基础的操作了,首先我们离散化,然后把矩形的上下边拆开存储,记录每个边是上边还是下边(读到上底加上这个长度,下底就减去)

想象一个平行于x轴的直线向上移,每次统计在扫描线上的线段长度,用长度乘以这段宽度

用线段树+1(底)/ -1(顶)去维护每段是否在当前的矩形内,计算它们的长度和即可

【代码】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int maxn=200+5;
typedef long long ll;
int n,tot;
struct segtree
{
    int mark;
    double len;
}tr[maxn<<2];
struct point
{
    double l,r,h;
    int di;
}p[maxn<<1];
bool cmp(point a,point b)
{
    return a.h<b.h;
}
double ls[maxn];
void push(int now,int l,int r)
{
    if(tr[now].mark)
    {
        tr[now].len=ls[r+1]-ls[l];
        return;
    }
    else if(l==r) tr[now].len=0;
    else tr[now].len=tr[now<<1].len+tr[now<<1|1].len;
}
void update(int now,int L,int R,int l,int r,int val)
{
    if(l>=L && R>=r)
    {
        tr[now].mark+=val;
        push(now,l,r);
        return;
    }
    int mid=l+r>>1;
    if(L<=mid) update(now<<1,L,R,l,mid,val);
    if(mid<R) update(now<<1|1,L,R,mid+1,r,val);
    push(now,l,r);
}
int main()
{
    freopen("area.in","r",stdin);
    freopen("area.out","w",stdout);
    int T=0;
    while(scanf("%d",&n) && n)
    {
        T++;
        memset(tr,0,sizeof(tr));
        double a,b,c,d,ans=0;
        tot=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
            ls[++tot]=a;
            p[tot]=(point){a,c,b,1};
            ls[++tot]=c;
            p[tot]=(point){a,c,d,-1};
        }
        sort(ls+1,ls+tot+1);
        sort(p+1,p+tot+1,cmp);
        int m=unique(ls+1,ls+tot+1)-ls-1;
        for(int i=1;i<=tot;i++)
        {
            int L=lower_bound(ls+1,ls+m+1,p[i].l)-ls;
            int R=lower_bound(ls+1,ls+m+1,p[i].r)-ls-1;
            update(1,L,R,1,m,p[i].di);
            ans+=(p[i+1].h-p[i].h)*tr[1].len;
        }
        printf("Test case #%d\n",T);
        printf("Total explored area: %.2f\n\n",ans);
    }
    return 0;
}

 

 
posted @ 2021-05-10 22:21  andyc_03  阅读(46)  评论(0编辑  收藏  举报