• Hdu1255 覆盖的面积


    覆盖的面积

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


    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   |   We have carefully selected several similar problems for you:  1698 1166 1540 1394 1754 
    分析:和Hdu1542类似,只是要求覆盖两次及以上的面积,那么线段树就要多记录一些东西.
              扫描线的线段树有点奇怪,修改的标记不会下传,标记的意义是当前区间被完整地覆盖了多少次,我们可以根据这个标记来求这个区间覆盖了至少一次的长度和至少两次的长度.分点和线来考虑,如果当前考虑的区间是个点,那么答案肯定是0,否则看标记,如果标记大于0了,那么覆盖了至少一次的长度可以直接算出来,如果标记大于1了,至少覆盖两次的长度也可以直接算出来.如果标记正好等于1,当前区间被完整地覆盖了一次,找到子区间被覆盖了至少一次的区间长度,两个子区间加起来就是答案.其它情况都要从子区间得到,类似于pushup.
              数组至少要开2倍......数组开小了竟然WA了不是RE......
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 5010;
    
    struct node
    {
        double l, r, h;
        int id;
    }e[maxn * 2];
    
    int tot, T, n, cnt, tag[maxn << 2];
    double ans, X[maxn], XX[maxn], sum2[maxn << 2], sum[maxn << 2];
    
    bool cmp(node a, node b)
    {
        return a.h < b.h;
    }
    
    int find(double x)
    {
        int l = 1, r = cnt;
        while (l <= r)
        {
            int mid = (l + r) >> 1;
            if (XX[mid] == x)
                return mid;
            else
            if (XX[mid] > x)
                r = mid - 1;
            else
                if (XX[mid] < x)
                    l = mid + 1;
        }
        return 0;
    }
    
    void pushup(int o, int l, int r)
    {
        if (tag[o])
            sum[o] = XX[r + 1] - XX[l];
        else
            if (l == r)
                sum[o] = 0;
            else
                sum[o] = sum[o * 2] + sum[o * 2 + 1];
    
        if (tag[o] > 1)
            sum2[o] = XX[r + 1] - XX[l];
        else
            if (l == r)
                sum2[o] = 0;
            else
                if (tag[o] == 1)
                    sum2[o] = sum[o * 2] + sum[o * 2 + 1];
                else
                    sum2[o] = sum2[o * 2 + 1] + sum2[o * 2];
    }
    
    void update(int o, int l, int r, int x, int y, int v)
    {
        if (x <= l && r <= y)
        {
            tag[o] += v;
            pushup(o, l, r);
            return;
        }
        int mid = (l + r) >> 1;
        if (x <= mid)
            update(o * 2, l, mid, x, y, v);
        if (y > mid)
            update(o * 2 + 1, mid + 1, r, x, y, v);
        pushup(o, l, r);
    }
    
    int main()
    {
        scanf("%d", &T);
        while (T--)
        {
            memset(tag, 0, sizeof(tag));
            memset(sum, 0, sizeof(sum));
            memset(sum2, 0, sizeof(sum2));
            memset(X, 0, sizeof(X));
            memset(XX, 0, sizeof(XX));
            ans = 0.0;
            cnt = tot = 0;
            scanf("%d", &n);
            for (int i = 1; i <= n; i++)
            {
                double a, b, c, d;
                scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
                e[++tot].l = a;
                e[tot].r = c;
                e[tot].h = b;
                e[tot].id = 1;
                X[tot] = a;
                e[++tot].l = a;
                e[tot].r = c;
                e[tot].h = d;
                e[tot].id = -1;
                X[tot] = c;
            }
            sort(e + 1, e + 1 + tot, cmp);
            sort(X + 1, X + 1 + tot);
            XX[1] = X[1];
            cnt = 1;
            for (int i = 2; i <= tot; i++)
                if (X[i] != X[i - 1])
                    XX[++cnt] = X[i];
            for (int i = 1; i < tot; i++)
            {
                int l = find(e[i].l), r = find(e[i].r) - 1;
                update(1, 1, cnt, l, r, e[i].id);
                ans += (e[i + 1].h - e[i].h) * sum2[1];
            }
            printf("%.2lf
    ", ans);
        }
    
        return 0;
    }
  • 相关阅读:
    WinForm控件常用设置(转)
    EF Core性能优化(一)
    如何更改已经释放的(released)传输请求(TR)的描述
    在新窗口调用Tcode[ABAP4_CALL_TRANSACTION]
    [代码]如何取得表/结构的列名字(cl_abap_structdescr)
    [代码]创建.ZIP压缩文件[CL_ABAP_ZIP]
    如何在表维护视图(maintenance view)上添加自定义按钮(SM30)
    [代码]基于动态内表的ALV
    物料单位转换函数[MD_CONVERT_MATERIAL_UNIT]
    拆分全路径名得到路径+文件名[STPU1_EXTRACT_FILENAME]
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8010601.html
Copyright © 2020-2023  润新知