首页 > 代码库 > HDU 1255 覆盖的面积(线段树扫描线)

HDU 1255 覆盖的面积(线段树扫描线)

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
 
线段树扫描线:
跟上一题类似,不过既然求重叠面积,要求覆盖次数要两次以上。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<bitset>
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
typedef long long LL;
typedef pair<int,int>pil;
const int maxn=2000+100;
struct node{
    int l,r;
    int c;//记录重叠次数
    double lf,rf;
    double len1,len2;//len1,len2分别为覆盖一次,两次的长度
}t[maxn<<2];
struct Line{
    double x,y1,y2;
    int f;
}line[maxn];
double y[maxn];
int cas,n;
int cmp(Line l1,Line l2)
{
    return l1.x<l2.x;
}
void build(int l,int r,int rs)
{
    t[rs].l=l;t[rs].r=r;
    t[rs].c=0;
    t[rs].len1=t[rs].len2=0;
    t[rs].lf=y[l];
    t[rs].rf=y[r];
    if(l+1==r)  return ;
    int mid=(l+r)>>1;
    build(l,mid,rs<<1);
    build(mid,r,rs<<1|1);
}
void pushup(int rs)
{
    if(t[rs].c>=2)
    {
        t[rs].len1=t[rs].len2=t[rs].rf-t[rs].lf;
        return ;
    }
    else if(t[rs].c==1)
    {
        t[rs].len1=t[rs].rf-t[rs].lf;
        if(t[rs].l+1==t[rs].r)  t[rs].len2=0;
        else   t[rs].len2=t[rs<<1].len1+t[rs<<1|1].len1;
    }
    else
    {
        if(t[rs].l+1==t[rs].r)  t[rs].len1=t[rs].len2=0;
        else
        {
            t[rs].len1=t[rs<<1].len1+t[rs<<1|1].len1;
            t[rs].len2=t[rs<<1].len2+t[rs<<1|1].len2;
        }
    }
}
void update(int rs,Line e)
{
    if(e.y1==t[rs].lf&&e.y2==t[rs].rf)
    {
        t[rs].c+=e.f;
        pushup(rs);
        return ;
    }
    if(e.y2<=t[rs<<1].rf) update(rs<<1,e);
    else if(e.y1>=t[rs<<1|1].lf)  update(rs<<1|1,e);
    else
    {
        Line temp=e;
        temp.y2=t[rs<<1].rf;
        update(rs<<1,temp);
        temp=e;
        temp.y1=t[rs<<1|1].lf;
        update(rs<<1|1,temp);
    }
    pushup(rs);
}
int main()
{
   double x1,y1,x2,y2;
   scanf("%d",&cas);
   while(cas--)
   {
       scanf("%d",&n);
       int tt=1;
       REP(i,n)
       {
           scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
           line[tt].x=x1;
           line[tt].y1=y1;
           line[tt].y2=y2;
           line[tt].f=1;
           y[tt]=y1;
           tt++;
           line[tt].x=x2;
           line[tt].y1=y1;
           line[tt].y2=y2;
           line[tt].f=-1;
           y[tt]=y2;
           tt++;
       }
       sort(line+1,line+tt,cmp);
       sort(y+1,y+tt);
       build(1,tt-1,1);
       update(1,line[1]);
       double ans=0;
       for(int i=2;i<tt;i++)
       {
           ans+=t[1].len2*(line[i].x-line[i-1].x);
           update(1,line[i]);
       }
       printf("%.2f\n",ans);
   }
   return 0;
}


HDU 1255 覆盖的面积(线段树扫描线)