hdu 1542(扫描线+线段树区间更新)

题意:

求矩形面积的并


解题思路:

先将x坐标离散化,扫描线从底向上扫描。所以通过步骤,我们只记录平行与x走的线段,定义结构体

struct segment{

int l,r,h;// l表示该选段的左坐标,r表示该线段的有坐标,h表示改线         段的高度

bool flag;//表示该线段是所在矩形的上边还是下边

};

所以我们根据线段的h轴进行从小到大排序,遇到下边对将对应的区间[l,r-1]更新导线段树中

我们用[l,r-1]来取代[l,r]来进行保存因为我们这里保存的是一段距离

,所以线段树的某一个节点表示的意思是该dis[节点.R+1] - dis[该节点.L ],这样返回的就是当前矩形x坐标覆盖的总距离。


注意:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define MAXN0 500
#define eps 1e-8
#define l1(x) (x)<<1
#define r1(x) (x)>>1
int dcmp(double x);
struct segment{
    double l,r,h;
    bool flag;
    void set(double ll,double rr,double hh,bool ff){
        l = ll;
        r = rr;
        h = hh;
        flag = ff;
    }
    friend bool operator<(segment aa,segment bb){
        int tmp0 = dcmp(aa.h - bb.h);
        return tmp0<0;
    }
};
struct TRnode{
    int L,R;
    int c,num;
    double Len;
};
TRnode TR[MAXN0<<2];
segment seg[MAXN0];
double x[MAXN0];
int cntx,cnts;
int dcmp(double x){
    if(fabs(x)<eps){
        return 0;
    }
    return x<0?-1:1;
}
int cmp(double aa,double bb){
    return dcmp(aa-bb)<0;
}
void buildTR(int L,int R,int k){
    TR[k].L = L;
    TR[k].R = R;
    TR[k].Len = 0;
    TR[k].num = 0;
    TR[k].c = -1;
    if(L==R)return;
    int k1,k11,mid;
    k1 = l1(k);
    k11 = k1 + 1 ;
    mid = r1(L+R);
    buildTR(L, mid, k1);
    buildTR(mid+1,R,k11);
}
//void pd(int k,int k1,int k11){
//    TR[k1].c = TR[k11].c = TR[k].c;
//    if(TR[k].c==0){
//        TR[k1].Len = TR[k1].R - TR[k1].L + 1;
//        TR[k11].Len = TR[k11].R - TR[k11].L + 1;
//    }
//    else {
//        TR[k1].Len = 0;
//        TR[k11].Len = 0;
//    }
//    TR[k].c = -1;
//}
void pu(int k,int k1,int k11){
    if(!TR[k].num)
        TR[k].Len = TR[k1].Len + TR[k11].Len;
}
void update(int L,int R,int k,bool w){
    if(TR[k].L==L&&TR[k].R==R){
        if(w==0){
            if(!TR[k].num){
                TR[k].Len = x[R] - x[L-1];
            }
            TR[k].num++;
        }
        else {
            --TR[k].num;
            if(TR[k].num==0){
                int k1,k11;
                k1 = l1(k);
                k11 = k1+1;
                pu(k,k1,k11);
            }
        }
        
        return;
    }
    int k1,k11;
    k1 = l1(k);
    k11 = k1 + 1;
    //    if(TR[k].c>-1){
    //        pd(k,k1,k11);
    //    }
    int mid = r1(TR[k].L+TR[k].R);
    if(mid>=R){
        update(L,R,k1,w);
    }
    else if(mid<L){
        update(L,R,k11,w);
    }
    else{
        update(L,mid,k1,w);
        update(mid+1,R,k11,w);
    }
    pu(k,k1,k11);
}
double query(int k){
    return TR[k].Len;
}
void prepro(){
    sort(x,x+cntx,cmp);
    int tcnt = 0;
    x[tcnt++] = x[0];
    for(int i=1;i<cnts;++i){
        if(!dcmp(x[i]-x[i-1]))continue;
        x[tcnt++] = x[i];
    }
    cntx = tcnt;
    sort(seg,seg+cnts);
    buildTR(1, cntx, 1);
}
int bin(double xg){
    int L = 0,R = cntx - 1;
    int mid,tmp0;
    while(L<R){
        mid = r1(L+R);
        tmp0 = dcmp(x[mid] - xg);
        if(!tmp0){
            return ++mid;
            //break;
        }
        if(tmp0>0){
            R  = mid;
        }
        else{
            L = L+1;
        }
    }
    return ++L;
}
double solve(){
    int i=0;
    int up = cnts - 1;
    double area = 0;
    int tmp0;
    double tmp1;
    int L,R;
    double len = 0;
    while(i<up){
        tmp0 = dcmp(seg[i+1].h - seg[i].h);
        L = bin(seg[i].l);
        R = bin(seg[i].r);
        if(!tmp0){
            update(L,R-1,1,seg[i].flag);
        }
        else {
            update(L,R-1,1,seg[i].flag);
            double   H = seg[i+1].h - seg[i].h;
            area = area + H*query(1);
        }
        ++i;
    }
    return area;
}
int main(){
    int n;
    int cas = 0;
    double x1,x2,y1,y2;
    while(scanf("%d",&n)!=EOF){
        if(!n)break;
        cntx = 0;
        cnts = 0;
        for(int i=0;i<n;++i){
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            x[cntx++] = x1;
            x[cntx++] = x2;
            seg[cnts++].set(x1,x2,y1,false);
            seg[cnts++].set(x1,x2,y2,true);
        }
        prepro();
        double area = solve();
        printf("Test case #%d\n",++cas);
        printf("Total explored area: %.2lf\n\n",area);
    }
    return 0;
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值