码迷,mamicode.com
首页 > 其他好文 > 详细

poj1511,线段树扫描线面积

时间:2018-11-11 01:01:38      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:ios   upd   int   string   test   长度   def   ring   can   

经典题,线段树扫描线其实类似区间更新,一般的做法是想象一根扫描线从上扫到下或者从左扫到右,本题的做法是从上扫到下

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define maxn 2000
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
struct Seg{
    double l,r,h;
    int d;
    Seg(){}
    Seg(double a,double b,double c,int dd):l(a),r(b),h(c),d(dd){}
    bool operator<(const Seg & a)const{
        return h<a.h;
    }//从下往上扫描
}segs[maxn];//横线段
double data[maxn];
int tot,m;//data统计高度
int cnt[maxn<<2];//覆盖了这一整个区间的入边数 - 覆盖了这一整个区间的出边数 
double sum[maxn<<2];//区间当前被覆盖的长度
inline void pushup(int l,int r,int rt){
    //前两个if对应的是update中(L<=l && R>=r)的pushup,后一个if对应的是分开更新后的update
    if(cnt[rt])//如果这个区间都被覆盖了
        sum[rt]=data[r+1]-data[l];
    else if (l==r)//如果是单位段并且cnt[rt]==0,说明这一段就是没有被覆盖
        sum[rt]=0;
    else sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
//更新函数update:如果整个区间被更新,分三种情况:1.这个区间被完全覆盖 2.这个区间是空白单位区间(没有子区间) 3.这个区间没有被完全覆盖 
void update(int L,int R,int c,int l,int r,int rt){
    if(L<=l && R>=r){
        cnt[rt]+=c;
        pushup(l,r,rt);//为什么这里也会有pushup?因为pushup的功能不只是合并两个区间而已,它还能计算这个区间的覆盖长度 
        return; 
    }
    int m=l+r>>1;
    if(L<=m) update(L,R,c,lson);
    if(R>m) update(L,R,c,rson);
    pushup(l,r,rt);
}
void init(){
    tot=m=0;
    memset(cnt,0,sizeof cnt);
    memset(sum,0,sizeof sum);
}
int main(){
    int T=0,n;
    while(scanf("%d",&n) && n){
        init();
        
        for(int i=1;i<=n;i++){
            double x1,y1,x2,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            segs[tot]=Seg(x1,x2,y1,1);data[tot++]=x1;
            segs[tot]=Seg(x1,x2,y2,-1);data[tot++]=x2;
        }
        sort(segs,segs+tot);
        sort(data,data+tot);
        m=unique(data,data+tot)-data;

        double ret=0;
        for(int i=0;i<tot;i++){
            int posl=lower_bound(data,data+m,segs[i].l)-data;
            int posr=lower_bound(data,data+m,segs[i].r)-data-1;
            if(posl<=posr) 
                update(posl,posr,segs[i].d,0,m,1);//把这条边更新到线段树中
            ret+=sum[1]*(segs[i+1].h-segs[i].h);
        }
        printf("Test case #%d\nTotal explored area: %.2lf\n\n",++T , ret);
    }
    return 0;
}

 

poj1511,线段树扫描线面积

标签:ios   upd   int   string   test   长度   def   ring   can   

原文地址:https://www.cnblogs.com/zsben991126/p/9941032.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!