zoukankan      html  css  js  c++  java
  • hdu 1255 覆盖的面积 (扫描线求矩形交)

    覆盖的面积

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


    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

    题目大意:

    求n个矩形重复覆盖的面积。

    线段树求矩形交的经典题。

    首先离散化还是要去重,即使是浮点数,我的去重离散化模板还是稳得住的。

    其次线段树节点中的cov要理解好。

    最后跟标准线段树可以有些不同的,毕竟query永远是全部询问。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<stack>
    #define ll long long
    #define maxn 1000
    
    using namespace std;
    
    double t[maxn*4+5];//排序数组
    double a[maxn*4+5];//原始数据
    int b[maxn*4+5];//离散后的数据
    double to[maxn*4+5];//离散后的数据到原数据的映射
    
    struct tseg
    {
        int x1,x2,y;
        int flag;//+1表示下边,-1表示上边
        bool operator<(const tseg& b) const
        {
            return y<b.y;
        }
    };
    tseg seg[maxn*2+5];
    
    struct ttree
    {
        int l,r;
        int cov;//cov是扫描线的重点 -1不确定 >=0完全覆盖次数
        inline double len()
        {
            return to[r]-to[l];
        }
    };
    ttree tree[maxn*4*4+5];
    
    void pushup(int x)
    {
        if(tree[x].l+1==tree[x].r)
            return;
        if(tree[x*2].cov==tree[x*2+1].cov)
            tree[x].cov=tree[x*2].cov;
        else
            tree[x].cov=-1;
    }
    
    void pushdown(int x)
    {
        if(tree[x].l+1==tree[x].r)
            return;
        if(tree[x].cov>=0)
            tree[x*2].cov=tree[x*2+1].cov=tree[x].cov;
    }
    
    void build(int x,int l,int r)
    {
        tree[x].l=l;
        tree[x].r=r;
        tree[x].cov=0;
        if(l+1<r)
        {
            int mid=(l+r+1)/2;
            build(x*2,l,mid);
            build(x*2+1,mid,r);
        }
    }
    
    void modify(int x,int l,int r,int op)
    {
        if(l<=tree[x].l&&r>=tree[x].r&&tree[x].cov>=0)
        {
            tree[x].cov+=op;
        }
        else
        {
            pushdown(x);
            int mid=(tree[x].l+tree[x].r+1)/2;
            if(l<mid)
                modify(x*2,l,r,op);
            if(r>mid)
                modify(x*2+1,l,r,op);
            pushup(x);
        }
    }
    
    //扫描线的query可以简略着写,因为一定是全部查询
    double query(int x)
    {
        if(tree[x].cov>=2)
            return tree[x].len();
        else if(tree[x].cov==0||tree[x].cov==1)
            return 0;
        else
        {
            pushdown(x);
            double ret=0;
            ret+=query(x*2);
            ret+=query(x*2+1);
            return ret;
        }
    }
    
    int main()
    {
        int tt;
        scanf("%d",&tt);
        while(tt--)
        {
            int n;
            scanf("%d",&n);
            for(int i=0;i<n*4;i++)
            {
                scanf("%lf",a+i);
                t[i]=a[i];
            }
            sort(t,t+n*4);
            int m=unique(t,t+n*4)-t;//编号1..m
            for(int i=0;i<n*4;i++)
            {
                b[i+1]=lower_bound(t,t+m,a[i])-t+1;
                to[b[i+1]]=a[i];
            }
    
            for(int i=1,j=1;i<=n*4;i+=4,j+=2)
            {
                seg[j]=(tseg){b[i],b[i+2],b[i+1],1};
                seg[j+1]=(tseg){b[i],b[i+2],b[i+3],-1};
            }
            sort(seg+1,seg+1+n*2);
    
            build(1,1,m);
            double ans=0;
            for(int i=1;i<=n*2;i++)
            {
                if(i>=2)
                {
                    double len=query(1);
                    ans+=len*(to[seg[i].y]-to[seg[i-1].y]);
                }
                modify(1,seg[i].x1,seg[i].x2,seg[i].flag);
             }
    
            printf("%.2f
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    解决UITableView中Cell重用机制导致内容出错的方法总结
    Hdu 1052 Tian Ji -- The Horse Racing
    Hdu 1009 FatMouse' Trade
    hdu 2037 今年暑假不AC
    hdu 1559 最大子矩阵
    hdu 1004 Let the Balloon Rise
    Hdu 1214 圆桌会议
    Hdu 1081 To The Max
    Hdu 2845 Beans
    Hdu 2955 Robberies 0/1背包
  • 原文地址:https://www.cnblogs.com/acboyty/p/9943677.html
Copyright © 2011-2022 走看看