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

来源:互联网 发布:vb msg 编辑:程序博客网 时间:2024/05/22 10:23

覆盖的面积

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)


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


 

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

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

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

Sample Input
251 1 4 21 3 3 72 1.5 5 4.53.5 1.25 7.5 46 3 10 730 0 1 11 0 2 12 0 3 1
 

Sample Output
7.630.00线段树计算被覆盖部分的面积
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <string>#include <algorithm>#include <queue>#include <vector>#include <map>#define LL long longusing namespace std;const int Max = 1000;typedef struct Tree{    int num;    double OneL,TwoL;//记录区间被覆盖多于一次和两次的长度}Tree;Tree Tr[Max*10];typedef struct Point{    double x;    double y1;    double y2;    int op;    bool operator < (const struct Point a)const    {        return x<a.x;    }}Point;Point P[Max*3];vector <double>y;int T,n;void Pushup(int L,int R,int st){    if(Tr[st].num>=2)    {        Tr[st].TwoL=Tr[st].OneL=y[R-1]-y[L-1];        return ;    }    if(Tr[st].num==1)    {        if(L+1==R)        {            Tr[st].TwoL=0;            Tr[st].OneL=y[R-1]-y[L-1];        }        else        {            Tr[st].OneL=y[R-1]-y[L-1];            Tr[st].TwoL=Tr[st<<1].OneL+Tr[st<<1|1].OneL;        }        return ;    }    if(Tr[st].num==0)    {        if(L+1==R)        {            Tr[st].OneL=Tr[st].TwoL=0;        }        else        {            Tr[st].OneL=Tr[st<<1].OneL+Tr[st<<1|1].OneL;            Tr[st].TwoL=Tr[st<<1].TwoL+Tr[st<<1|1].TwoL;        }        return ;    }}void Build(int L,int R,int st){    Tr[st].num=0;    Tr[st].OneL=Tr[st].TwoL=0;    if(L+1==R)    {        return ;    }    int mid = (L+R)>>1;    Build(L,mid,st<<1);    Build(mid,R,st<<1|1);    Pushup(L,R,st);}void Update(int L,int R,int st,int l,int r,int d){    if(l>=R||r<=L)    {        return ;    }    if(L>=l&&R<=r)    {        Tr[st].num+=d;        Pushup(L,R,st);        return ;    }    int mid = (L+R)>>1;    if(l<=mid)    {        Update(L,mid,st<<1,l,r,d);    }    if(r>mid)    {        Update(mid,R,st<<1|1,l,r,d);    }    Pushup(L,R,st);}int main(){    double x1,x2,y1,y2;    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        y.clear();        map<double ,int >M;        int m=0;        for(int i=0;i<n;i++)        {            scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);            P[m].x=x1; P[m].y1=y1; P[m].op=1; P[m++].y2=y2;            P[m].x=x2; P[m].y1=y1; P[m].op=-1; P[m++].y2=y2;            y.push_back(y1);            y.push_back(y2);        }        sort(P,P+m);        sort(y.begin(),y.end());        y.erase(unique(y.begin(),y.end()),y.end());//去重        int sum = y.size();        for(int i=0;i<sum;i++)//重新编号        {            M[y[i]]=i+1;        }        double Area =0 ;        double h;        Build(1,sum,1);        for(int i=0;i<m-1;i++)        {            Update(1,sum,1,M[P[i].y1],M[P[i].y2],P[i].op);            h=P[i+1].x-P[i].x;            Area += (h*Tr[1].TwoL);//计算面积        }        printf("%.2f\n",Area);    }    return 0;}


0 0