poj1151矩形面积并

这篇博客介绍了如何利用线段树解决POJ1151题目中的矩形面积合并问题。作者分享了学习的新离散化技巧,并详细阐述了首次尝试构建线段树来处理线段相关问题的心得。文章通过个人对扫描线算法的理解,解释了在不断添加边或权值时如何逐步计算当前部分的几何信息。
摘要由CSDN通过智能技术生成

学习了一种新的离散化

第一次写有关线段的线段树

个人理解的扫描线:每添加一条边(或权值)就算当前这一部分的东西,然后再添加,一个循环

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 200
int n,T,t;
double x1,x2,y1,y2,ans;
struct point{
 double x,y1,y2;
 int flag;
}node[2*MAXN];
struct tpoint{
   int l,r,s;
   double len,ml,mr;
}tree[4*MAXN];

double y[2*MAXN];



int comp(const point &a,const point &b)
{
    return a.x<b.x+0.00000001;
}
//tree[p].len表示tree[p].ml~tree[p].mr之间被线段覆盖的总长度
//tree[p].s表示tree[p].ml~tree[p].mr之间被几条线段覆盖
//并且tree[p].s>0表示这条线段被完全覆盖
void build(int p,int l,int r)
{
    tree[p].l=l;
    tree[p].r=r;
    tree[p].ml=y[l];//离散化
    tree[p].mr=y[r];
    tree[p].s=0;
    tree[p].len=0;
    if (tree[p].l+1==tree[p].r)
        return ;
    int mid=(l+r) >> 1;
    build(p<<1,l,mid);
    build(p<<1^1,mid,r);
}
void callen(int p)//算tree[p].len
{
    if (tree[p].s>0)
        tree[p].len=tree[p].mr-tree[p].ml;
    else
        if (tree[p].l+1==tree[p].r)
          tree[p].len=0;
        else
           tree[p].len=tree[p<<1].len+tree[p<<1^1].len;
    return ;
}
void updata(int p,point t)
{
    if (tree[p].ml==t.y1 && tree[p].mr==t.y2)
    {
        tree[p].s+=t.flag;
        callen(p);
        return ;
    }
    double mid=tree[p<<1].mr;
    if (t.y2<=mid) updata(p<<1,t);
    if (t.y1>=mid) updata(p<<1^1,t);
    if (t.y1<mid && t.y2>mid)
    {
        point tmp=t;
        tmp.y2=mid;
        updata(p<<1,tmp);
        tmp=t;
        tmp.y1=mid;
        updata(p<<1^1,tmp);
    }
    callen(p);//每一次更新了tree[p]的子节点,就要更新p的len,保证每次只取tree[1].len即可
    return ;
}
int main()
{
    while (scanf("%d", &n) && (n))
    {
        T++;
        t=0;
        for (int i=1;i<=n;i++)
        {
            scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
            t++;
            y[t]=y1;
            node[t].x=x1;
            node[t].y1=y1;
            node[t].y2=y2;
            node[t].flag=1;
            t++;
            y[t]=y2;
            node[t].x=x2;
            node[t].y1=y1;
            node[t].y2=y2;
            node[t].flag=-1;
        }
        sort(node+1,node+t+1,comp);
        sort(y+1,y+t+1);
        build(1,1,t);
        ans=0;
        updata(1,node[1]);
        for (int i=2;i<=t;i++)
        {
            ans+=(node[i].x-node[i-1].x)*tree[1].len;
            updata(1,node[i]);
        }
        printf("Test case #%d\n",T);
        printf("Total explored area: %.2lf\n\n",ans);
    }
    return 0;

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值