• 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
  • 相关阅读:
    13 原型链_继承_this大总结_函数一定是对象,对象不一定是函数
    12 贪吃蛇游戏
    实现wiki访问
    11 第三个阶段js高级_原型
    JZOJ.5257【NOIP2017模拟8.11】小X的佛光
    模板——权值线段树(逆序对)
    LCA模板
    笛卡尔树——神奇的“二叉搜索堆”
    JZOJ.5246【NOIP2017模拟8.8】Trip
    JZOJ.5236【NOIP2017模拟8.7】利普希茨
  • 原文地址:https://www.cnblogs.com/acboyty/p/9943677.html
Copyright © 2020-2023  润新知