首页 > 其他分享 >POJ1151(线段树+扫描线求矩形面积并)

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

时间:2023-05-31 18:39:21浏览次数:56  
标签:POJ1151 cov int double 线段 tree mid len 扫描线


题目: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;
}

 

标签:POJ1151,cov,int,double,线段,tree,mid,len,扫描线
From: https://blog.51cto.com/u_16146153/6388728

相关文章

  • POJ1151(矩形切割入门题)
    题目:Atlantis 我的上一篇文章已经讲明了线段切割的思想,矩形切割就是把线段切割从一维推到二维就行了,思想都一样。#include<stdio.h>#include<string.h>constintN=205;typedefstruct{doublex1,y1;doublex2,y2;doublesum;}Node;NodeT[N];intn......
  • POJ2886线段树 Joseph游戏(单点更新)
    题目:WhoGetstheMostCandies? 题意:1.n个人进行Joseph游戏,游戏共p轮(p为思路:用相对坐标来处理,例如这一轮出局的是p,下一个要+m,则p出局时p+1就变成了p(因为是相对坐标),则下一个人应该是p+m-1,再注意循环和m的正负的处理,不要忘了取模。2.求解原始序号时维护一棵线段树,类似上一题插队......
  • POJ2528 线段树+离散化+hash(成段更新)
    题目:Mayor'sposters 题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报思路:这题数据范围很大,直接搞超时+超内存,需要离散化:离散化简单的来说就是只取我们需要的值来用,比如说区间[1000,2000],[1990,2012]我们用不到[-∞,999][1001,1989][1991,1999][2001,2011][201......
  • poj 2985(并查集+线段树求K大数)
    解题思路:这道题并查集很容易,合并时找到父节点就直接加上去就ok了。关键是如何求K大数,我一直在想用线段树怎么写,一开始想如果直接记录数的大小那肯定是没戏了,借鉴了一下别人的思路:区间[a,b]记录的是所有的数里面,等于a,a+1,a+2,......,b-1,b的个数。看到这里就应该明白了,这里线段树的用法......
  • hdu 4027(线段树)
    题意:给定100000个数,两种操作,0ij表示将ij这段的数字都开根号(向下取整),1ij表示查询ij之间的所有值的和。。。(所有的和都不超过64位)解题思路:这题要做区间的开平方操作,2^64最多可以做8次开平方操作,所以对于每个节点最多只有8次操作,这道题如果lazy思想的话就要保存每个区间被开平方......
  • hdu 3564(线段树+LIS)
    题意:给出1~n的插入顺序,要求每次插入之后的LIS解题思路:这道题确实挺难想的,我最开始想用树状数组每插入一个数就更新一次,如果这么想,那么你就输了。它这里的想法是先将1-n的最终位置都保存起来,然后再一个个去找LIS。这里有点离线算法的意思,至少了解到更新时可以先别急着处理。还有这里......
  • hdu 3303(线段树+抽屉原理)
    解题思路:这题利用了抽屉原理,即1-M之间的所有数与M+1的模都不相同。那么可以利用它将要查找所有区间分成[1,Y-1],[Y,2*Y-1],[2*Y,3*Y-1].........一直下去,直到所有的区间都被找一遍,然后就是保存最小的模即可。。。这样就肯定要找每个区间的最小的模,实际上这里可以利用线段树去找,只需......
  • hdu 3577(线段树区间更新)
    题意:输入一个t,表示有t组测试数据;         接下来一行,输入两个数,k,m,其中k表示这个辆车最多可以坐这么多人,m表示有m次询问能否上车;         每一次询问,输入两个数a,b,表示该乘客能否在a站台上车,b站台下车,乘车区间为(a,b--),先后次序;         即我每次询......
  • hihocoder #1078 : 线段树的区间修改
    解题思路:基础的线段树区间修改我按照书上敲的代码不知道为什么WA。。。#include<iostream>#include<cstdio>#include<cstring>usingnamespacestd;constintmaxn=1e5;intn,q,l,r,_sum;intsetv[maxn<<2],sum[maxn<<2];voidmaintain(into,intL,intR){ intl......
  • hdu 2795(线段树)
    解题思路:这道题很难想到是用线段树,确实转化的很巧妙实际上,我们只需要利用线段树(记录1-h)维护哪个位置的剩余空间最大即可,即1,2,......,h是线段树的叶子节点,我们每次要找的就是叶子节点的剩余空间的最大值,只要能够想到这里就很容易啦。。另外如果h>n的话,就令h=n,否则就是类似于位置多......