hdu 1542 线段树扫描线

第一次写二维线段树,听队友说各种纠结看不懂。刷完HH大牛的专辑中的一维了,怀着忐忑的心情看二维线段树,首先看最简单的,面积并。题意很简单啊,知道是二维线段树,想了想完全没思路。然后各种百度谷歌,找了几篇看着顺眼的blog看了思想,纠结了一小时左右,总算大概懂了。再看看HH的代码,简直是神来之笔,各种疑问蜂拥而至。跟队友讨论了n久,只剩PushUp和更新有点小纠结了。考虑到时间比较晚了,今天晚上就准备结束了。事后我又想了想,似乎有有点头绪了,果断又开电脑继续奋战,似乎是完全看懂了。然后自己敲了个代码纵向扫描,果断各种错误啊,接下来就是深入理解HH的代码了。在蛋疼了三小时之后,终于迎来了一道曙光,测试数据总算过了。不管结果如何,先submit,没想到,嘿嘿,居然Ac了,实在有点小兴奋啊。也算是了解了一点点二维线段树,虽说只是最基础的,不过我相信半个月之后也能达到入门级别啦。为自己加油!!!


ACcode:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using std::sort;

const int size=1111;

struct Seg
{
    double ly,ry,hx;
    int f;
    Seg(){}
    Seg(double a,double b,double c,int d):ly(a),ry(b),hx(c),f(d){}
    bool operator < (const Seg &cmp)const {
        return hx<cmp.hx;
    }

}seg[size<<2];

struct Line
{
    double len;
    int v;
}tre[size<<2];

double Y[size<<1];

void build(int rt,int l,int r)
{
    tre[rt].len=0;
    tre[rt].v=0;
    if (l==r) return ;
    int m=(l+r)>>1;
    build(rt<<1,l,m);
    build(rt<<1|1,m+1,r);
}

void PushUp(int rt,int l,int r)
{
    if (tre[rt].v)tre[rt].len=Y[r+1]-Y[l];
    else if (l==r) tre[rt].len=0;
    else tre[rt].len=tre[rt<<1].len+tre[rt<<1|1].len;
}

void update(int rt,int l,int r,int L,int R,int v)
{
    if (L<=l&&r<=R)
    {
        tre[rt].v+=v;
        PushUp(rt,l,r);
        return ;
    }
    int m=(l+r)>>1;
    if (L<=m) update(rt<<1,l,m,L,R,v);
    if (R>m)  update(rt<<1|1,m+1,r,L,R,v);
    PushUp(rt,l,r);
}

int Bin(double key,int k,double Y[])
{
    int l=0,r=k;
    while (l<=r)
    {
        int m=(l+r)>>1;
        if (Y[m]==key) return m;
        else if (Y[m]<key) l=m+1;
        else r=m-1;
    }
    return -1;
}

int main()
{
    int n,m,i,k,L,R,cas=0;
    double x1,x2,y1,y2,ans;
    while (scanf("%d",&n)&&n)
    {
        m=0;
        for (i=0;i<n;i++)
        {
            scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
            Y[m]=y1;Y[m+1]=y2;
            seg[m++]=Seg(y1,y2,x1,1);
            seg[m++]=Seg(y1,y2,x2,-1);
        }
        sort(Y,Y+m);
        sort(seg,seg+m);
        for (k=0,i=1;i<m;i++)
            if (Y[i]!=Y[i-1]) Y[++k]=Y[i];
        build(1,0,k-1);
        for (ans=i=0;i<m-1;i++)
        {
            L=Bin(seg[i].ly,k,Y);
            R=Bin(seg[i].ry,k,Y)-1;
            if (L<=R) update(1,0,k-1,L,R,seg[i].f);
            ans+=tre[1].len*(seg[i+1].hx-seg[i].hx);
        }
        printf("Test case #%d\nTotal explored area: %.2lf\n\n",++cas,ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值