• HDU1255 扫描线 矩形交面积 离散化


    覆盖的面积

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


    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
     

    题意:

    给出矩形左下和右上角的坐标,求矩形交的面积。

    代码:

    //cnt[rt]>=2的一定是覆盖过两次以上的,直接计算。cnt[rt]==1时,如果rt的左右儿子
    //被覆盖过大于等于1次,那么再被他们父亲覆盖上就是覆盖过两次了,值是左右儿子被
    //覆盖过一次的长度的和。cnt[rt]==0照常更新。sum2记录覆盖过两次以上的边的长度。
    //sum1记录覆盖过一次的边的长度。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=2005;
    double sum1[maxn*4],sum2[maxn*4],mp[maxn];
    int cnt[maxn*4];
    struct node{
        double l,r,h;
        int d;
        node(){}
        node(double a,double b,double c,int d):l(a),r(b),h(c),d(d){}
        bool operator < (const node &p)const{
            if(h==p.h) return d>p.d;
            return h<p.h;
        }
    }nodes[maxn*4];
    int Bsearch(double a,int b,double *c)
    {
        int l=0,r=b-1,mid;
        while(l<=r){
            mid=(l+r)>>1;
            if(c[mid]==a) return mid;
            else if(c[mid]>a) r=mid-1;
            else l=mid+1;
        }
        return -1;
    }
    void Pushup(int l,int r,int rt)
    {
        if(cnt[rt]){
            sum1[rt]=mp[r+1]-mp[l];
            if(cnt[rt]==1)
                sum2[rt]=sum1[rt<<1]+sum1[rt<<1|1];
            else sum2[rt]=mp[r+1]-mp[l];
        }
        else if(l==r) sum1[rt]=sum2[rt]=0;
        else{
            sum1[rt]=sum1[rt<<1]+sum1[rt<<1|1];
            sum2[rt]=sum2[rt<<1]+sum2[rt<<1|1];
        }
    }
    void Update(int ql,int qr,int v,int l,int r,int rt)
    {
        if(ql<=l&&qr>=r){
            cnt[rt]+=v;
            Pushup(l,r,rt);
            return;
        }
        //if(l==r) return;
        int m=(l+r)>>1;
        if(ql<=m) Update(ql,qr,v,l,m,rt<<1);
        if(qr>m) Update(ql,qr,v,m+1,r,rt<<1|1);
        Pushup(l,r,rt);
    }
    int main()
    {
        int t,n;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            int m=0,nu=0;
            double x1,y1,x2,y2;
            memset(sum1,0,sizeof(sum1));
            memset(sum2,0,sizeof(sum2));
            memset(cnt,0,sizeof(cnt));
            for(int i=0;i<n;i++){
                scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
                nodes[m++]=node(x1,x2,y1,1);
                nodes[m++]=node(x1,x2,y2,-1);
                mp[nu++]=x1;mp[nu++]=x2;
            }
            sort(mp,mp+nu);
            nu=unique(mp,mp+nu)-mp;
            sort(nodes,nodes+m);
            double ans=0;
            for(int i=0;i<m-1;i++){
                int lef=Bsearch(nodes[i].l,nu,mp);
                int rig=Bsearch(nodes[i].r,nu,mp)-1;
                if(lef<=rig)
                    Update(lef,rig,nodes[i].d,0,nu-1,1);
                ans+=sum2[1]*(nodes[i+1].h-nodes[i].h);
            }
            printf("%.2lf
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    JIRA Activity Stream连接到FishEye时路径不对
    职业分析
    Doublechecked locking解析
    Wireshark基本介绍和学习TCP三次握手
    插入排序算法
    Event.observe
    前端开发工程师如何在2013年里提升自己
    addEventListener(转)
    最好的HTML 5编码教程和参考手册分享
    XSRF 的攻击与防范
  • 原文地址:https://www.cnblogs.com/--ZHIYUAN/p/6628262.html
Copyright © 2020-2023  润新知