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

    覆盖的面积

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

    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

     题意:求矩形面积的交。

    分析:就是矩形面积并的一个升级版,在求并时,重复多少次我们并没有管,现在要叫我们求至少相交2次的面积,为此可以在结构体中增加一个变量ss,表示覆盖2次及以上的区间长度,s表示覆盖一次的长度,改变的就只有计算长度的那个函数,如何计算ss:

    1.cnt>1 : 说明该区间被覆盖两次或以上,那么长度就可以直接计算,就是该区间的长度

    剩下的情况就是cnt=1或cnt=0

    2.先看叶子节点,因为是叶子没有孩子了,所以被覆盖两次货以上的长度就是0(无论cnt=1或cnt=0都是0,因为是叶子。。。)

    3.不是叶子节点 ,且cnt=1.注意这里,cnt=1确切的意义是什么,应该是,可以确定,这个区间被完全覆盖了1次,而有没有被完全覆盖两次或以上则不知道无法确定,那么怎么怎么办了,只要加上t[lch].s + t[rch].s  即,看看左右孩子区间被覆盖了一次或以上的长度,那么叠加在双亲上就是双亲被覆盖两次或以上的长度

    3.不是叶子节点,且cnt=0,确切的意义应该是不完全不知道被覆盖的情况(不知道有没有被覆盖,被覆盖了几次,长度是多少都不知道),这种情况,只能由其左右孩子的信息所得

    t[lch].ss + t[rch].ss  , 即直接将左右孩子给覆盖了两次或以上的长度加起来。

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    const int MAXN = 1100;
    struct Node
    {
        int l,r;
        double cnt;//该节点的覆盖情况
        double s,ss;
    }segTree[2*MAXN*4];
    struct Segment
    {
        double l,r,h;
        int f;
    }ss[MAXN*2];
    double pos[MAXN*2];
    
    bool cmp(const Segment& aa,const Segment& bb)
    {
        return aa.h<bb.h;
    }
    void build(int id,int l,int r)
    {
        segTree[id].l=l;
        segTree[id].r=r;
        segTree[id].cnt=0;
        segTree[id].s=0;
        segTree[id].ss=0;
        if(l==r) return;
        int mid=(l+r)/2;
        build(id*2,l,mid);
        build(id*2+1,mid+1,r);
    }
    void calen(int id)
    {
        if(segTree[id].cnt)
            segTree[id].s=pos[segTree[id].r+1]-pos[segTree[id].l];
        else if(segTree[id].l==segTree[id].r) segTree[id].s=0;
        else segTree[id].s=segTree[id*2].s+segTree[id*2+1].s;
        if(segTree[id].cnt>1)
            segTree[id].ss=pos[segTree[id].r+1]-pos[segTree[id].l];
        else if(segTree[id].l==segTree[id].r) segTree[id].ss=0;
        else if(segTree[id].cnt==1)
            segTree[id].ss=segTree[id*2].s+segTree[id*2+1].s;
        else segTree[id].ss=segTree[id*2].ss+segTree[id*2+1].ss;
    }
    void update(int id,int l,int r,int val)
    {
        if(segTree[id].l==l&&segTree[id].r==r)
        {
            segTree[id].cnt+=val;
            calen(id);
            return;
        }
        int mid=(segTree[id].l+segTree[id].r)/2;
        if(l>mid) update(id*2+1,l,r,val);
        else if(r<=mid) update(id*2,l,r,val);
        else
        {
            update(id*2,l,mid,val);
            update(id*2+1,mid+1,r,val);
        }
        calen(id);
    }
    
    int main()
    {
        int T;
        int n;
        double x1,y1,x2,y2;
        scanf("%d",&T);
        while(T--)
        {
            int t=1;
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
            {
                scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
                ss[t].l=x1,ss[t].r=x2,ss[t].h=y1,ss[t].f=1,pos[t]=x1,t++;
                ss[t].l=x1,ss[t].r=x2,ss[t].h=y2,ss[t].f=-1,pos[t]=x2,t++;
            }
            sort(ss+1,ss+t,cmp);
            sort(pos+1,pos+t);
            //for(int i=1; i<t; i++) printf("%.2lf %.2lf  %.2lf
    ",ss[i].l,ss[i].r,ss[i].h);
            int m=2;
            for(int i=2;i<t;i++)
                if(pos[i]!=pos[i-1])
                    pos[m++]=pos[i];
            build(1,1,m-1);
            double ans=0;
            for(int i=1;i<t;i++)
            {
                int l=lower_bound(pos+1,pos+m,ss[i].l)-pos;
                int r=lower_bound(pos+1,pos+m,ss[i].r)-pos-1;
                //cout<<l<<" "<<r<<endl;
                update(1,l,r,ss[i].f);
                ans+=(ss[i+1].h-ss[i].h)*segTree[1].ss;
            }
            printf("%.2lf
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    ACM士兵排队
    ACM两个士兵打牌
    ACM平衡的括号
    ACM复合词
    ACM第二次比赛( C )
    ACM比赛(第二次A)
    ACM比赛(进制转换)
    ACM比赛(11462 Age Sort)
    ACM比赛
    hdu 1241 Oil Deposits(DFS求连通块)
  • 原文地址:https://www.cnblogs.com/wangdongkai/p/5742898.html
Copyright © 2011-2022 走看看