zoukankan      html  css  js  c++  java
  • HDU 1255 覆盖的面积[离散化 + 扫描线 + 线段树]

    http://acm.hdu.edu.cn/showproblem.php?pid=1255
    给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.

    这里写图片描述

    这题比hdu1542复杂一点点(here),就是要求至少被覆盖两次。
    其实也没复杂多少。在线段树维护的时候只需用 len[node][i] 表示 node 结点被覆盖至少 i 次的长度就好了。

    精度问题?我样例跑出来是7.62,但也A了。。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    #define rep(i,f,t) for(int i = (f),_end = (t); i <= _end; ++i)
    #define clr(c,x) memset(c,x,sizeof(c));
    #define debug(x) cout<<"debug  "<<x<<endl;
    
    const double eps = 1e-9;
    
    typedef pair<double,double> Pr;
    vector<double> vs;
    int n;
    
    struct Node{
        double x,y1,y2;
        int from,to;
        bool flag;
        Node(double xx,double yy1,double yy2,double f)
            :x(xx),y1(yy1),y2(yy2),flag(f){}
        bool operator<(const Node &n2)const{
            return x < n2.x;
        }
    };
    vector<Node> line;
    
    bool equ(double a,double b){ return fabs(a-b)<eps; }
    bool cmp(double a,double b){
        if(equ(a,b))return false;
        return a < b;
    }
    
    const int maxn = 2002<<2;
    #define MID int mid = (L+R)>>1;
    #define CHD int lc = node<<1, rc = node<<1|1;
    
    struct sgt{
        int cov[maxn];
        double len[maxn][3];
        void init(){
            clr(cov,0);
            clr(len,0);
        }
        void update(int from,int to,int tp,int node,int L,int R){
            if(from <= L && R <= to){
                cov[node] += tp;
            }else{
                MID;CHD;
                if(from <= mid)update(from,to,tp,lc,L,mid);
                if(to > mid)update(from,to,tp,rc,mid+1,R);
            }
            maintain(node,L,R);
        }
        void maintain(int node,int L,int R){
            double tot = vs[R]-vs[L-1];
            clr(len[node],0);
            rep(i,1,min(2,cov[node]))
                len[node][i] = tot;
            if(L==R)return;
            CHD;
            rep(i,cov[node]+1,2){
                len[node][i] = len[lc][i-cov[node]] + len[rc][i-cov[node]];
            }
        }
        double query(){
            return len[1][2];
        }
    }tree;
    
    void pre(){
        sort(vs.begin(),vs.end());
        vs.erase(unique(vs.begin(),vs.end(),equ),vs.end());
        rep(i,0,line.size()-1){
            line[i].from = lower_bound(vs.begin(),vs.end(),line[i].y1,cmp) - vs.begin();
            line[i].to = lower_bound(vs.begin(),vs.end(),line[i].y2,cmp) - vs.begin();
        }
    }
    
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            vs.clear();
            line.clear();
            scanf("%d",&n);
            rep(i,1,n){
                double x1,y1,x2,y2;
                scanf("%lf%lf%lf%lf", &x1,&y1,&x2,&y2);
                vs.push_back(y1);
                vs.push_back(y2);
                line.push_back(Node(x1,y1,y2,true));
                line.push_back(Node(x2,y1,y2,false));
            }
            pre();//离散化
            sort(line.begin(),line.end());
            double ans = 0;
            double x = 0;
            rep(i,0,line.size()-1){
                int v = (line[i].flag ? 1 : -1);
                double len = tree.query();
                ans += (line[i].x-x)*len;
                x = line[i].x;
                tree.update(line[i].from+1,line[i].to,v,1,1,vs.size()-1);
            }
            printf("%.2lf
    ",ans);
        }
        return 0;
    }
    

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    我要好offer之 二叉树大总结
    我要好offer之 字符串相关大总结
    楼层扔鸡蛋问题[转]
    Linux System Programming 学习笔记(十一) 时间
    Linux System Programming 学习笔记(十) 信号
    Linux System Programming 学习笔记(九) 内存管理
    Linux System Programming 学习笔记(八) 文件和目录管理
    Linux System Programming 学习笔记(七) 线程
    Linux System Programming 学习笔记(六) 进程调度
    APUE 学习笔记(十一) 网络IPC:套接字
  • 原文地址:https://www.cnblogs.com/DSChan/p/4861975.html
Copyright © 2011-2022 走看看