• 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;
    }
  • 相关阅读:
    分布式缓存HttpRuntime.cache应用到单点登陆中_优化登陆
    ID Codes
    Smith Numbers经典
    青蛙的约会
    exp_euler两种形式int,void(扩展欧几里得算法)可求最大公约数,二元一次方程的解
    A/B
    Raising Modulo Numbers
    Brave balloonists 求素因子的个数
    排列
    Anagram
  • 原文地址:https://www.cnblogs.com/dashuzhilin/p/4550872.html
Copyright © 2020-2023  润新知