HDU - 1255 覆盖的面积 —— 扫描线

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lngxling/article/details/81325166

覆盖的面积

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 7404    Accepted Submission(s): 3732


 

Problem Description

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

 

 

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

思路:

扫描线,用线段树维护当前投影到x轴上的覆盖一次和两次的长度

大体不变,只要更改一下回溯的更新函数(代码里的up函数)

len1表示覆盖一次的长度,len2表示覆盖两次的长度,s表示覆盖的次数

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <vector>
#include <bitset>
#define max_ 1010
#define inf 0x3f3f3f3f
#define ll long long
#define les 1e-8
#define mod 364875103
using namespace std;
struct node
{
    int l,r;
    int s;
    double len1,len2;
};
struct node tree[max_*8];
struct edge
{
    double l,r;
    double h;
    int f;
    bool operator < (const edge &a)const
    {
        return h<a.h;
    }
};
struct edge e[max_*2];
int n;
double x[max_*2];
void built(int i,int l,int r)
{
    tree[i].l=l;
    tree[i].r=r;
    tree[i].s=0;
    tree[i].len1=tree[i].len2=0;
    if(l+1==r)
    return;
    int mid=(l+r)>>1;
    built(i<<1,l,mid);
    built(i<<1|1,mid,r);
}
void up(int i)
{
    if(tree[i].s>=2)
    tree[i].len1=tree[i].len2=x[tree[i].r]-x[tree[i].l];
    else if(tree[i].s==1)
    {
        tree[i].len1=x[tree[i].r]-x[tree[i].l];
        if(tree[i].l+1==tree[i].r)
        tree[i].len2=0;
        else
        tree[i].len2=tree[i<<1].len1+tree[i<<1|1].len1;
    }
    else
    {
        if(tree[i].l+1==tree[i].r)
        {
            tree[i].len1=tree[i].len2=0;
        }
        else
        {
            tree[i].len1=tree[i<<1].len1+tree[i<<1|1].len1;
            tree[i].len2=tree[i<<1].len2+tree[i<<1|1].len2;
        }
    }
}
void updata(int i,int l,int r,int v)
{
    if(tree[i].l==l&&tree[i].r==r)
    {
        tree[i].s+=v;
        up(i);
        return;
    }
    int mid=(tree[i].l+tree[i].r)>>1;
    if(r<=mid)
    updata(i<<1,l,r,v);
    else if(l>=mid)
    updata(i<<1|1,l,r,v);
    else
    {
        updata(i<<1,l,mid,v);
        updata(i<<1|1,mid,r,v);
    }
    up(i);
}
int main(int argc, char const *argv[]) {
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            double x1,x2,y1,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            int p=i*2-1;
            int q=i*2;
            e[p].l=e[q].l=x1;
            e[p].r=e[q].r=x2;
            e[p].h=y1;
            e[q].h=y2;
            e[p].f=1;
            e[q].f=-1;
            x[p]=x1;
            x[q]=x2;
        }
        sort(x+1,x+1+2*n);
        sort(e+1,e+1+2*n);
        built(1,1,2*n);
        double ans=0;
        for(int i=1;i<2*n;i++)
        {
            int l=lower_bound(x+1,x+1+2*n,e[i].l)-x;
            int r=lower_bound(x+1,x+1+2*n,e[i].r)-x;
            updata(1,l,r,e[i].f);
            ans+=tree[1].len2*(e[i+1].h-e[i].h);
        }
        printf("%.2f\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Lngxling/article/details/81325166
今日推荐