首页 > 代码库 > [codevs3044]矩形面积求并

[codevs3044]矩形面积求并

题目描述 Description
输入n个矩形,求他们总共占地面积(也就是求一下面积的并)
输入描述 Input Description

可能有多组数据,读到n=0为止(不超过15组)

每组数据第一行一个数n,表示矩形个数(n<=100)

接下来n行每行4个实数x1,y1,x2,y1(0 <= x1 < x2 <= 100000;0 <= y1 < y2 <= 100000),表示矩形的左下角坐标和右上角坐标

输出描述 Output Description
每组数据输出一行表示答案
样例输入 Sample Input
2
10 10 20 20
15 15 25 25.5
0
样例输出 Sample Output
180.00
数据范围及提示 Data Size & Hint
 无

 矩形面积并,扫描线+线段树

本题的线段树比较奇怪
其中的坑点在pushup,线段树维护的区间[l,r]如果l,r相等并不是一段空集,而是线段pos[l]-pos[r+1] 这一线段

技术分享
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
#define mem(a,b) memset(a,b,sizeof(a))
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c==-)f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-0;c=getchar();}
    return x*f;
}
const int maxn=210;
int n,add[maxn<<2];
double a,b,c,d,pos[maxn],sum[maxn<<2],ans;
struct segment
{
    double X,x,Y;int tag;
    segment(){}
    segment(double _1,double _2,double _3,int _4):X(_1),x(_2),Y(_3),tag(_4) {}
    bool operator < (const segment &s)const {return Y<s.Y;}
}seg[maxn];
void pushup(int l,int r,int o)
{
    if(add[o])sum[o]=pos[r+1]-pos[l];
    else if(l==r)sum[o]=0;
    else sum[o]=sum[o<<1]+sum[o<<1|1];
}
void update(int l,int r,int o,int L,int R,int c)
{
    if(L==l && r==R)
    {
        add[o]+=c;
        pushup(l,r,o);
        return;
    }
    int mid=(l+r)>>1,lo=o<<1,ro=lo|1;
    if(R<=mid)update(l,mid,lo,L,R,c);
    else if(L>mid)update(mid+1,r,ro,L,R,c);
    else update(l,mid,lo,L,mid,c),update(mid+1,r,ro,mid+1,R,c);
    pushup(l,r,o);
}
int main()
{
    while(scanf("%d",&n)!=EOF && n)
    {
        mem(pos,0);mem(sum,0);mem(add,0);ans=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
            seg[i*2]=segment(a,c,b,1);pos[i*2]=a;
            seg[i*2-1]=segment(a,c,d,-1);pos[i*2-1]=c;
        }
        sort(seg+1,seg+n*2+1);sort(pos+1,pos+n*2+1);
        for(int i=1;i<=2*n;i++)
        {
            int l=lower_bound(pos+1,pos+n*2+1,seg[i].X)-pos;
            int r=lower_bound(pos+1,pos+n*2+1,seg[i].x)-pos-1;
            update(1,2*n,1,l,r,seg[i].tag);
            ans+=sum[1]*(seg[i+1].Y-seg[i].Y);
        }
        printf("%.2lf\n",ans);
    }
    return 0;
}
View Code

 

[codevs3044]矩形面积求并