zoukankan      html  css  js  c++  java
  • zoj 1659 Mobile Phone Coverage(矩形面积并)

    题意:每组数据给出正方形中点坐标及半边长,求矩形面积并;

    思路:采用沿垂直方向计算矩形面积并的方法,把面积切成若干垂直条再累加。zoj上能过,但Uva688却一直RE,已经尝试过开大空间了。。。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const double epsi=1e-10;
    const int maxn=40000;
    struct line{
        double x,y1,y2;   //x坐标及上下端点y坐标
        int s;
        line(double a=0,double b=0,double c=0,int d=0):x(a),y1(b),y2(c),s(d){}
        bool operator <(const line &op2) const{
            return x<op2.x; //按x坐标递增排序
        }
    };
    extern double ly[maxn<<1];   //上下边的y坐标
    class Tree{
        int cover;             //并区间标志
        Tree *child[2];        //左右儿子指针
        void deliver(){        //调整覆盖
            if(cover)   //若并区间未结束,则覆盖区间长度为ly[r]-ly[l];否则覆盖区间长度为左右子树的覆盖区间长度之和
                len=ly[r]-ly[l];
            else
                len=child[0]->len+child[1]->len;
        }
    public:
        int l,r;
        double len;       //垂直条长度
        void setup(int ll,int rr){
            l=ll;r=rr;
            cover=0;len=0;
            if(ll+1==rr) return;  //若区间无法二分,则返回
            int mid=(l+r)/2;
            child[0]=new Tree(),child[1]=new Tree();
            child[0]->setup(ll,mid),child[1]->setup(mid,rr);//构造左右子树
        }
        void paint(const int &ll,const int &rr,const int &v){ //往区间为[l,r]的线段树插入边界标志为v的垂直条[ll,rr]
            if(ll>=r||rr<=l) return;
            if(ll<=l&&r<=rr){     //若[ll,rr]覆盖[l,r]则调整区间长度len
                if(cover+=v) len=ly[r]-ly[l];
                else{
                    if(child[0]==NULL) len=0;
                    else
                    len=child[0]->len+child[1]->len;
                }
                return;
            }
            child[0]->paint(ll,rr,v),child[1]->paint(ll,rr,v);//递归左右子树
            deliver();//调整覆盖区间长度
        }
        void del(){
            if(child[0]){ //若左子树存在,则递归删除左右子树
                child[0]->del();
                delete child[0];
                child[1]->del();
                delete child[1];
            }
        }
    };
    int cas=0;
    int n,m,tot,ty;  //l表的长度为tot,ly表的长度为ty
    line l[maxn<<1];  //存储垂直条
    double ly[maxn<<1]; //存储地图上下边的y坐标
    Tree *seg;   //线段树指针
    int main(){
        while(scanf("%d",&n)!=EOF){
            if(n==0) break;
            tot=ty=0;
            for(int i=0;i<n;i++){
                double x,y,r;
                scanf("%lf%lf%lf",&x,&y,&r);
                l[tot++]=line(x-r,y-r,y+r,1);
                l[tot++]=line(x+r,y-r,y+r,-1);
                ly[ty++]=y-r;ly[ty++]=y+r;
            }
            sort(l,l+tot);
            sort(ly,ly+ty);
            ty=unique(ly,ly+ty)-ly;//使用unique函数,除去ly[]中的重复元素
            double ans=0;
            seg=new Tree();
            seg->setup(0,ty-1);
            for(int i=0,j;i<tot;i=j){
                if(i) ans+=seg->len*(l[i].x-l[i-1].x);
                j=i; //依次枚举右方的垂直条,取出底边的y坐标在ly中的序号l,顶边的y坐标在ly中的序号r,左右边界标志k,将[l,r,k]插入线段树
                while(j<tot&&fabs(l[i].x-l[j].x)<=epsi){
                      seg->paint(lower_bound(ly,ly+ty,l[j].y1)-ly,lower_bound(ly,ly+ty,l[j].y2)-ly,l[j].s);
                      ++j;
                }
            }
            seg->del();
            delete seg;
            printf("%d %.2f
    ",++cas,ans);
        }
        return 0;
    }
  • 相关阅读:
    关于JSON可能出现的错误,待更/todo
    mongoose的安装与使用(书签记录) 2017
    HTTP的学习记录3--HTTPS和HTTP
    HTTP的学习记录(二)头部
    HTTP(一)概述
    LeetCode 455. Assign Cookies
    LeetCode 453. Minimum Moves to Equal Array Elements
    LeetCode 448. Find All Numbers Disappeared in an Array
    LeetCode 447. Number of Boomerangs
    LeetCode 416. Partition Equal Subset Sum
  • 原文地址:https://www.cnblogs.com/dashuzhilin/p/4550872.html
Copyright © 2011-2022 走看看