zoukankan      html  css  js  c++  java
  • 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;
    }

  • 相关阅读:
    2019.6.20刷题统计
    36 线程 队列 守护线程 互斥锁 死锁 可重入锁 信号量
    35 守护进程 互斥锁 IPC 共享内存 的方式 生产者消费者模型
    34 进程 pid ppid 并发与并行,阻塞与非阻塞 join函数 process对象 孤儿进程与僵尸进程
    33 udp 域名 进程
    32 粘包 文件传输
    31 socket客户端. 服务器 异常 语法
    30 网络编程
    29 元类 异常
    26 封装 反射 常用内置函数
  • 原文地址:https://www.cnblogs.com/kuangbin/p/2140779.html
Copyright © 2011-2022 走看看