POJ1151(线段树+扫描线求矩形面积并)

题目:http://poj.org/problem?id=1151

 

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>

using namespace std;
const int N = 10005;

struct node
{
    int l,r;
    int cov;
    double len;
};

struct line
{
    double x;
    double y1;
    double y2;
    int f;
    bool operator < (const line &a) const
    {
        return x < a.x;
    }
};

class SegTree
{
    private:
        node tree[N];
        double num[N];
        int ncount;

    public:

        SegTree(double a[],int n)
        {
            for(int i=0;i<n;i++)
                num[i] = a[i];
            ncount = n;
            Build(0,n-1,1);
        }

        void Build(int l,int r,int rt)
        {
            tree[rt].l = l;
            tree[rt].r = r;
            tree[rt].cov = 0;
            tree[rt].len = 0;
            if(l+1 == r) return;
            int mid = (l+r)>>1;
            Build(l,mid,2*rt);
            Build(mid,r,2*rt+1);
        }

        void Insert(int l,int r,int p)
        {
            if(tree[p].l == l && tree[p].r == r)
            {
                tree[p].cov++;
                tree[p].len = num[r] - num[l];
                return;
            }
            int mid = (tree[p].l + tree[p].r)>>1;
            if(r <= mid)
                Insert(l,r,2*p);
            else if(l >= mid)
                Insert(l,r,2*p+1);
            else
            {
                Insert(l,mid,2*p);
                Insert(mid,r,2*p+1);
            }
            if(tree[p].cov == 0)
                tree[p].len = tree[2*p].len + tree[2*p+1].len;
        }

        void Delete(int l,int r,int p)
        {
            if(tree[p].l == l && tree[p].r == r)
            {
                tree[p].cov--;
                if(tree[p].cov <= 0)
                {
                    if(tree[p].l+1 < tree[p].r)
                        tree[p].len = tree[2*p].len + tree[2*p+1].len;
                    else
                        tree[p].len = 0;
                }
                return;
            }
            int mid = (tree[p].l + tree[p].r)>>1;
            if(r <= mid)
                Delete(l,r,2*p);
            else if(l >= mid)
                Delete(l,r,2*p+1);
            else
            {
                Delete(l,mid,2*p);
                Delete(mid,r,2*p+1);
            }
            if(tree[p].cov == 0)
                tree[p].len = tree[2*p].len + tree[2*p+1].len;
        }

        double getLen()
        {
            return tree[1].len;
        }
};

int main()
{
    int test=0,n;
    double x1,y1,x2,y2;
    double yval[N];
    line data[N];
    while(~scanf("%d",&n))
    {
        if(n==0) break;
        test++;
        int l1 = 0;
        int l2 = 0;
        for(int i=0;i<n;i++)
        {
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            yval[l1++] = y1;
            yval[l1++] = y2;
            data[l2].x = x1;
            data[l2].y1 = y1;
            data[l2].y2 = y2;
            data[l2].f = -1;
            l2++;
            data[l2].x = x2;
            data[l2].y1 = y1;
            data[l2].y2 = y2;
            data[l2].f = 1;
            l2++;
        }
        sort(yval,yval+l1);
        sort(data,data+l2);
        l1 = unique(yval,yval+l1) - yval;
        double sum = 0;
        SegTree stree(yval,l1);
        for(int i=0;i<l2-1;i++)
        {
            int l,r;
            l = lower_bound(yval,yval+l1,data[i].y1) - yval;
            r = lower_bound(yval,yval+l1,data[i].y2) - yval;
            if(data[i].f == -1)
                 stree.Insert(l,r,1);
            else
                 stree.Delete(l,r,1);
            sum += stree.getLen() * (data[i+1].x - data[i].x);
        }
        printf("Test case #%d\n", test);
		printf("Total explored area: ");
		printf("%.2lf\n\n", sum);
    }
    return 0;
}


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值