zoukankan      html  css  js  c++  java
  • 扫描线,线段树,离散化——HDU

    题目含义

    每一行给出两个点,代表一个矩形的左下角端点和右上角端点

    要你求出这些矩形覆盖坐标轴的整个面积

    题目分析

    用平行x轴的扫描线扫描整个图形,得到很多长宽不同的矩形,求出面积再相加

    将每个矩形的面积记作 len(x)*len(y)

    每个len(x)我们通过加减每个点的x左右坐标,通过线段树求sum[1]得到

    每个len(y)我们通过这个点与下一个点的y坐标的差得到

    所以我们要把所有点按y轴大小排序,并且记录每个点的左右x轴坐标

    注意:这里用的线段树sum【l,r】不是指区间【l,r】的和,而是指X.l和X.r的差

    题目代码

    #include<stdio.h>
    #include<iostream>
    #include<vector>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    const int maxn=1e5+7;
    typedef long long LL;
    vector<double>v;
    int n;
    double x1,y1,x2,y2;
    double len[maxn<<2];
    int cov[maxn<<2];
    struct node{
        double y,x1,x2;
        int k;
    }rem[maxn];
    int getid(double x){
        return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
    }
    bool cmp(node a,node b){
        return a.y<b.y;
    }
    void pushup(int l,int r,int rt){
        if(cov[rt]>0)len[rt]=v[r]-v[l-1];
        else if(l==r)len[rt]=0;
        else len[rt]=len[rt<<1]+len[rt<<1|1];
    }
    void updata(int l,int r,int rt,int ll,int rr,int k){
        if(ll<=l&&r<=rr){
            cov[rt]+=k;
            pushup(l,r,rt);
            return;
        }
        int mid=(l+r)>>1;
        if(ll<=mid)updata(l,mid,rt<<1,ll,rr,k);
        if(rr>mid)updata(mid+1,r,rt<<1|1,ll,rr,k);
        pushup(l,r,rt);
    }
    int main(){
        int ce=0;
        while(scanf("%d",&n)&&n){
            memset(len,0,sizeof(len));
            memset(cov,0,sizeof(cov));
            v.clear();
            int cnt=0;
            for(int i=0;i<n;i++){
                scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
                v.push_back(x1);
                v.push_back(x2);
                rem[++cnt].x1=x1,rem[cnt].x2=x2,rem[cnt].y=y1,rem[cnt].k=1;
                rem[++cnt].x1=x1,rem[cnt].x2=x2,rem[cnt].y=y2,rem[cnt].k=-1;
            }
            sort(v.begin(),v.end());
            v.erase(unique(v.begin(),v.end()),v.end());
            sort(rem+1,rem+1+cnt,cmp);
            double ans=0;
            for(int i=1;i<cnt;i++){
                updata(1,cnt,1,getid(rem[i].x1),getid(rem[i].x2)-1,rem[i].k);
                ans+=len[1]*(rem[i+1].y-rem[i].y);
            }
            printf("Test case #%d
    Total explored area: %.2f
    
    ",++ce,ans);
        }
        return 0;
    }
  • 相关阅读:
    什么是基于注解的容器配置?
    一个线程运行时发生异常会怎样?
    Java 中你怎样唤醒一个阻塞的线程?
    为什么 wait, notify 和 notifyAll 这些方法不在 thread 类里面?
    Java 中 notify 和 notifyAll 有什么区别?
    在 Spring MVC 应用程序中使用 WebMvcTest 注释有什么用处?
    java 中有几种方法可以实现一个线程?
    什么是AOP?
    什么是竞争条件?你怎样发现和解决竞争?
    Mybatis 是如何进行分页的?分页插件的原理是什么?
  • 原文地址:https://www.cnblogs.com/helman/p/11226607.html
Copyright © 2011-2022 走看看