N - Picture - poj 1177(扫描线求周长)

题意:求周长的,把矩形先进行融合后的周长,包括内周长

分析:刚看的时候感觉会跟棘手,让人无从下手,不过学过扫描线之后相信就很简单了吧(扫描线的模板- -),还是不说了,下面是一精确图,可以拿来调试数据

*****************************************************************************************************************

#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;

#define Lson r<<1
#define Rson r<<1|1

const int MAXN = 2e5+5;
const int oo = 1e9+7;

struct stgmentTree
{///len 保存区间包含的边的长度,cover 保存区间被覆盖的次数, sum保存有多少个不相连的区间段
    int L, R, len, cover, sum;
    bool lb, rb;///左边和右边是否被覆盖
    int mid(){return (R+L)>>1;}
}a[MAXN<<2];
///dir 等于 1 的时候代表左边,-1时候代表右边,右边会抵消左边
struct Point{int x, y1, y2, dir;}ege[MAXN];
int Hash[MAXN], nh;///保存离散化后的数据,nh表示元素个数

bool cmp(Point n1, Point n2)
{///把边按照x的值从左往右排序
    return n1.x < n2.x;
}
///查找一条边的长度, x1 < x2
int findSegLen(int x1, int x2)
{///用下标可以直接检索值
    return Hash[x2] - Hash[x1];
}
void buildTree(int r, int L, int R)
{
    a[r].L = L, a[r].R = R, a[r].cover=0;

if(L == R-1)return ;

buildTree(Lson, L, a[r].mid());
    buildTree(Rson, a[r].mid(), R);
}
void pushUp(int r)///合并操作
{///需要先注意本区间是否被覆盖
    if(a[r].cover != 0)
    {
        a[r].len= findSegLen( a[r].L, a[r].R );
        a[r].sum = a[r].lb = a[r].rb = 1;
    }
    else if(a[r].L == a[r].R - 1)
    {
        a[r].len = 0;
        a[r].sum = a[r].lb = a[r].rb = 0;
    }
    else
    {///如果本区间未被覆盖,并且不为叶子节点,那么就等于子区间的和
        a[r].len = a[Lson].len + a[Rson].len;

a[r].lb = a[Lson].lb, a[r].rb = a[Rson].rb;
        a[r].sum = a[Lson].sum + a[Rson].sum - (a[Lson].rb & a[Rson].lb);
    }

}
void upData(int r, int L, int R, int dir)
{
    if( a[r].L == L && a[r].R == R )
    {
        a[r].cover += dir;
        pushUp(r);

return ;
    }

if(R <= a[r].mid())
        upData(Lson, L, R, dir);
    else if(L >= a[r].mid())
        upData(Rson, L, R, dir);
    else
    {
        upData(Lson, L, a[r].mid(), dir);
        upData(Rson, a[r].mid(), R, dir);
    }

pushUp(r);
}

int main()
{
    int N;

while(scanf("%d", &N) != EOF)
    {
        int i, x1, x2, y1, y2, k=0, C=0, pre=0; nh = 0;

for(i=0; i<N; i++)
        {
            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
            ege[k].x=x1, ege[k].y1=y1, ege[k].y2=y2, ege[k++].dir=1;///左边y
            ege[k].x=x2, ege[k].y1=y1, ege[k].y2=y2, ege[k++].dir=-1;///右边y
            Hash[nh++] = y1, Hash[nh++] = y2;
        }

sort(Hash, Hash+nh);///排序去重复
        nh = unique(Hash, Hash+nh) - Hash;
        ///离散化后的数据是从0下标开始的
        buildTree(1, 0, nh-1);

///对边按照x排序
        sort(ege, ege+k, cmp);

for(i=0; i<k-1; i++)
        {
            int L = lower_bound(Hash, Hash+nh, ege[i].y1) - Hash;
            int R = lower_bound(Hash, Hash+nh, ege[i].y2) - Hash;

upData(1, L, R, ege[i].dir);

C += fabs(a[1].len - pre) + (ege[i+1].x - ege[i].x)*a[1].sum * 2;
            pre = a[1].len;
        }

printf("%d\n", C+pre);
    }

return 0;

}

时间: 2024-10-14 04:27:55

N - Picture - poj 1177(扫描线求周长)的相关文章

POJ 1177 Picture(扫描线求周长)

与求面积并的差不多,但是这个与扫描的方向相同的情况不太好处理,如果扫描线离散化两次扫两遍其实也可以解决这个问题,但是这样无论在时间还是空间上稍微就有点浪费了啊.这里因为我是离散x坐标的所以对于平行于y轴的方向上的统计比较难统计.处理的方法是:标记区间左边的断点,和右边的断点,求出这个区间一共有多少个断点.就可以统计出平行于y轴的长度了.这里合并的时候需要判断右边的左区间和左边的右区间是否相同,如果相同的话,说明他们连接到了一起,要减去多加的. Picture Time Limit: 2000MS

hdu1828 (Picture) &amp;poj 1177( Picture)&amp;sdibt 2390(5.5.1 Picture 矩形周长)(线段树+扫描)

题目地址:hdu1828 (Picture)  & poj 1177( Picture) & sdibt 2390(5.5.1 Picture 矩形周长) 题目大意: 给你N个矩形,求出N个矩形构成的周长. 解题思路: 线段数+扫描线. 推荐博客: POJ1177 Picture(线段树求轮廓周长) POJ 1177 Picture (线段树+离散化+扫描线) 详解 注意事项: 该题在求面积的基础上有了升级,多写了一个被调需要求出投影与Y轴有几段,不然样例会少算20,就是给出图形中间的小矩

POJ 1177 &amp; HDU 1828 Picture(扫描线 + 求周长)

题目链接: POJ:http://poj.org/problem?id=1177 HDU:http://acm.hdu.edu.cn/showproblem.php?pid=1828 几个不错的讲解: http://www.cnblogs.com/scau20110726/archive/2013/04/13/3018702.html http://blog.csdn.net/xingyeyongheng/article/details/8931410 Description A number

Picture POJ - 1177 线段树+离散化+扫描线 求交叉图像周长

参考  https://www.cnblogs.com/null00/archive/2012/04/22/2464876.html #include <stdio.h> #include <algorithm> #define LEN 10000 using namespace std; struct Node { int left; int right; int count;//被覆盖次数 //所包含的区间数量,如三条[1,2],[2,3],[4,5]线段被覆盖,则line=2

HDU 1828 Picture(线段树扫描线求周长)

Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4475    Accepted Submission(s): 2207 Problem Description A number of rectangular posters, photographs and other pictures of the same shap

Picture POJ - 1177(扫描线 + 线段树)

题意:求矩形并的面积.. 解析: 扫描线第一道题....自下而上扫描的... 如果不懂什么是扫描线戳我 #include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <set> #include <vector> #include <stack> #include <q

Picture POJ - 1177

A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or horizontal. Each rectangle can be partially or totally covered by the others. The length of the boundary of the un

POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的,这样理论上是对的 要注意处理高度相同的线段,把底边优先处理(在代码里就是f标记为1的线段),因为若是一个矩形的底边和另一个矩形的上边重合,则这个轮廓肯定不能算 不过POJ和HDU的数据好像都比较弱,我没进行上面的细节处理也AC了,不过一个很简单的数据就会不对,所以还是要处理一下才是真正正确的代码 我

poj 1177 Picture(扫描线+矩形周长并)

http://poj.org/problem?id=1177 求矩形的周长并,明确的一点是对于覆盖的边的长度忽略不计. 与求面积并类似,首先离散化,对矩形的每条横边从下往上扫描.扫描过程中要完成三个任务,更新相应的区间信息,求横边长,求竖边长. 节点信息: l,r:左右区间编号 cnt:表示该区间是否被完全覆盖.cnt > 0 表示完全覆盖,否则不完全覆盖. lp,rp:表示该区间的两个端点是否被覆盖,为1被覆盖,为0没被覆盖. num:该区间被覆盖的线段数目.例如区间[1,10],当更新[2,