• ACM HDU 1255 覆盖的面积(矩形面积交,线段树+离散化)


    覆盖的面积

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


    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
     

    Author
    Ignatius.L & weigang Lee
     

    Recommend
    Ignatius.L
     
     
    /*
    HDU 1255 覆盖的面积
    求矩形交的面积(线段树+离散化)
    给定一些矩形
    被这些矩形覆盖过至少两次的区域的面积
    */
    #include
    <stdio.h>
    #include
    <iostream>
    #include
    <algorithm>
    using namespace std;
    #define MAXN 2010
    struct Node
    {
    int l,r;//线段树的左右整点
    int c;//c用来记录重叠情况
    double lf,rf;//
    //rf,lf分别是对应的左右真实的浮点数端点
    double cnt,more;//cnt是值被覆盖一次以上的长度,more值被覆盖两次以上的长度
    }segTree[MAXN*3];
    struct Line
    {
    double x,y1,y2;
    int f;
    }line[MAXN];
    //把一段段平行于y轴的线段表示成数组 ,
    //x是线段的x坐标,y1,y2线段对应的下端点和上端点的坐标
    //一个矩形 ,左边的那条边f为1,右边的为-1,
    //用来记录重叠情况,可以根据这个来计算,nod节点中的c

    bool cmp(Line a,Line b)//sort排序的函数
    {
    return a.x < b.x;
    }

    double y[MAXN];//记录y坐标的数组
    void Build(int t,int l,int r)//构造线段树
    {
    segTree[t].l
    =l;segTree[t].r=r;
    segTree[t].cnt
    =segTree[t].c=0;
    segTree[t].lf
    =y[l];
    segTree[t].rf
    =y[r];
    if(l+1==r) return;
    int mid=(l+r)>>1;
    Build(t
    <<1,l,mid);
    Build(t
    <<1|1,mid,r);//递归构造
    }
    void calen(int t)//计算长度
    {
    if(segTree[t].c>=2)
    {
    segTree[t].more
    =segTree[t].cnt=segTree[t].rf-segTree[t].lf;
    return;
    }
    else if(segTree[t].c==1)
    {
    segTree[t].cnt
    =segTree[t].rf-segTree[t].lf;
    if(segTree[t].l+1==segTree[t].r) segTree[t].more=0;
    else segTree[t].more=segTree[t<<1].cnt+segTree[t<<1|1].cnt;
    }
    else
    {
    if(segTree[t].l+1==segTree[t].r) segTree[t].more=segTree[t].cnt=0;
    else
    {
    segTree[t].cnt
    =segTree[t<<1].cnt+segTree[t<<1|1].cnt;
    segTree[t].more
    =segTree[t<<1].more+segTree[t<<1|1].more;
    }
    }
    }
    void update(int t,Line e)//加入线段e,后更新线段树
    {
    if(e.y1==segTree[t].lf&&e.y2==segTree[t].rf)
    {
    segTree[t].c
    +=e.f;
    calen(t);
    return;
    }
    if(e.y2<=segTree[t<<1].rf) update(t<<1,e);
    else if(e.y1>=segTree[t<<1|1].lf) update(t<<1|1,e);
    else
    {
    Line tmp
    =e;
    tmp.y2
    =segTree[t<<1].rf;
    update(t
    <<1,tmp);
    tmp
    =e;
    tmp.y1
    =segTree[t<<1|1].lf;
    update(t
    <<1|1,tmp);
    }
    calen(t);
    }
    int main()
    {
    int i,n,t,T;
    double x1,y1,x2,y2;
    scanf(
    "%d",&T);
    while(T--)
    {
    scanf(
    "%d",&n);
    t
    =1;
    for(i=1;i<=n;i++)
    {
    scanf(
    "%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
    line[t].x
    =x1;
    line[t].y1
    =y1;
    line[t].y2
    =y2;
    line[t].f
    =1;
    y[t]
    =y1;
    t
    ++;
    line[t].x
    =x2;
    line[t].y1
    =y1;
    line[t].y2
    =y2;
    line[t].f
    =-1;
    y[t]
    =y2;
    t
    ++;
    }
    sort(line
    +1,line+t,cmp);
    sort(y
    +1,y+t);
    Build(
    1,1,t-1);
    update(
    1,line[1]);
    double res=0;
    for(i=2;i<t;i++)
    {
    res
    +=segTree[1].more*(line[i].x-line[i-1].x);
    update(
    1,line[i]);
    }
    printf(
    "%.2lf\n",res);
    }
    return 0;
    }

  • 相关阅读:
    CentOS6.5系统服务
    Linux下查看文件内容时去掉空行和#开头的注释行
    sql去重复(RecordNum )
    bootstrap-fileinput使用
    javascript事件失效l
    vs2015里,发布OSGI.NET
    视频允许播放禁止下载
    zTree模糊查询人员姓名:getNodesByParamFuzzy
    OSGI.NET,请求因HTTP状态404 失败:Not Found
    异常
  • 原文地址:https://www.cnblogs.com/kuangbin/p/2140779.html
Copyright © 2020-2023  润新知