zoukankan      html  css  js  c++  java
  • HDU1542 矩形面积并 扫描线段树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542

    题意:二维平面有n个平行于坐标轴的的矩形,要算矩形面积并

    有一个讲的很好的博客:https://blog.csdn.net/u013480600/article/details/22548393

    线段树是按叶节点来一个个维护的,一堆浮点数是不能直接维护的,需要离散化来维护。

    要注意我们线段树中每个叶节点(控制区间[L,L])不是指X[L]坐标,而是指区间[X[L],X[L+1]].线段树中其他节点控制的区间[L,R],也是指的x坐标轴的第L个区间到第R个区间的范围,也就是X[L]到X[R+1]坐标的范围.

    简而言之,维护的是区间。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define mid (l+r)/2
    using namespace std;
    typedef long long ll;
    const int maxn=1000+10;
    double dat[4*maxn];
    int lazy[maxn];
    double b[maxn];
    struct edge{
        double l,r,h;
        int cnt;
        friend bool operator < (edge x,edge y){
            return x.h<y.h;
        }
    }e[maxn];
    void pushup(int a,int l,int r){
        if(lazy[a])    dat[a]=b[r+1]-b[l];
        else    dat[a]=dat[a<<1]+dat[a<<1|1];
    }
    void update(int a,int l,int r,int s,int t,int k){
        if(s>r || t<l)    return;
        if(s<=l && r<=t){
            lazy[a]+=k;
            pushup(a,l,r);
            return;
        }
        if(s<=mid)    update(a<<1,l,mid,s,t,k);
        if(t>mid)    update(a<<1|1,mid+1,r,s,t,k);
        pushup(a,l,r);
    }
    int main(){
        int n;
        int T=0;
        while(~scanf("%d",&n)){
            memset(dat,0,sizeof(dat));
            memset(lazy,0,sizeof(lazy));
            memset(b,0,sizeof(b));
            memset(e,0,sizeof(e));
            if(n==0)    return 0;
            T++;
            int p=0,num=0;
            for(int i=1;i<=n;i++){
                double x1,x2,y1,y2;
                scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
                e[++p].l=x1;
                e[p].r=x2;
                e[p].h=y1;
                e[p].cnt=1;
                e[++p].l=x1;
                e[p].r=x2;
                e[p].h=y2; 
                e[p].cnt=-1;
                b[++num]=x1;
                b[++num]=x2;
            }
            sort(e+1,e+1+p);
            sort(b+1,b+1+num);
            int m=unique(b+1,b+1+num)-b-1;
            double ans=0;
            for(int i=1;i<p;i++){
                int l=lower_bound(b+1,b+m,e[i].l)-b;
                int r=lower_bound(b+1,b+m,e[i].r)-b;
                update(1,1,m-1,l,r-1,e[i].cnt);//记住r-1是关键,维护的是区间,一共有m-1个区间 
                ans+=dat[1]*(e[i+1].h-e[i].h);
            }
            printf("Test case #%d
    ",T);
            printf("Total explored area: %.2lf
    
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    linux之iptable案例
    nginx常用命令参数
    laravel中的多对多关系详解
    MySql计算时间差函数
    总结下Mysql分表分库的策略及应用
    swoole扩展实现真正的数据库连接池
    linux常用命令整理
    innodb mvcc实现机制
    mysqlslap 压力测试使用总结
    mysql索引总结
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/11330889.html
Copyright © 2011-2022 走看看