O - 覆盖的面积 (线段树+扫描线)

给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 

Input

输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000. 

注意:本题的输入数据较多,推荐使用scanf读入数据. 

Output

对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数. 

Sample Input

2
5
1 1 4 2
1 3 3 7
2 1.5 5 4.5
3.5 1.25 7.5 4
6 3 10 7
3
0 0 1 1
1 0 2 1
2 0 3 1

Sample Output

7.63
0.00

题解:大神博客有讲解扫描线:https://blog.csdn.net/qq_18661257/article/details/47658191 

#include<bits/stdc++.h>
using namespace std;
const int maxn=2011;
double sum1[maxn<<2],sum2[maxn<<2],area;
double x[maxn<<2];
int cnt[maxn<<2];
int t,n,top1,top2;
struct node
{
    double l,r,h;//一条边的信息:左端点的横坐标,右端点的横坐标,高度(即纵坐标)
    int d;  //标记:为1代表为一个矩形的下边,-1为上边
    bool operator < (const node&a)const//按高度从小到大排序
    {
        return h<a.h;
    }
} line[maxn<<2];
void pushup(int l,int r,int rt)
{
    if(cnt[rt])
        sum1[rt]=x[r+1]-x[l];
    else if(l==r)   //一定要加上~
        sum1[rt]=0;
    else
        sum1[rt]=sum1[rt*2]+sum1[rt*2+1];
    if(cnt[rt]>=2)
        sum2[rt]=x[r+1]-x[l];
    else if(l==r)       //这个也一定要加上
        sum2[rt]=0;
    else if(cnt[rt]==1)
        sum2[rt]=sum1[rt*2]+sum1[rt*2+1];
    else if(cnt[rt]==0)
        sum2[rt]=sum2[rt*2]+sum2[rt*2+1];
}
void update(int L,int R,int v,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        cnt[rt]+=v;
        pushup(l,r,rt);
        return ;
    }
    int mid=(l+r)/2;
    if(L<=mid)
        update(L,R,v,l,mid,rt*2);
    if(R>=mid+1)
        update(L,R,v,mid+1,r,rt*2+1);
    pushup(l,r,rt);
}
void Init()
{
    memset(sum1,0,sizeof(sum1));
    memset(sum2,0,sizeof(sum2));
    memset(cnt,0,sizeof(cnt));
    top1=0,top2=0,area=0;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        Init();
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
        {
            double x1,y1,x2,y2;
            scanf("%lf%lf%lf%lf",&x1, &y1, &x2,&y2);
            x[++top1]=x1;
            x[++top1]=x2;
            line[++top2]=(node)
            {
                x1,x2,y1,1
            };//记录下边
            line[++top2]=(node)
            {
                x1,x2,y2,-1
            };//记录上边
        }
        sort(x+1,x+1+top1);
        sort(line+1,line+1+top2);
        int k=unique(x+1,x+1+top1)-x-1;
        for(int i=1; i<top2; i++)
        {
            int L=lower_bound(x+1,x+1+k,line[i].l)-x;
            int R=lower_bound(x+1,x+1+k,line[i].r)-x;
            R--;
            update(L,R,line[i].d,1,k-1,1);
            area+=sum2[1]*(line[i+1].h-line[i].h);
        }
        printf("%.2lf\n", area);//用c++的输出流不对?用c语言的就A了

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43824158/article/details/88693764