POJ1177 Picture —— 求矩形并的周长 线段树 + 扫描线 + 离散化
题目链接:https://vjudge.net/problem/POJ-1177
Write a program to calculate the perimeter. An example with 7 rectangles is shown in Figure 1.
The corresponding boundary is the whole set of line segments drawn in Figure 2.
The vertices of all rectangles have integer coordinates.
Input
0 <= number of rectangles < 5000
All coordinates are in the range [-10000,10000] and any existing rectangle has a positive area.
Output
Sample Input
7
-15 0 5 10
-5 8 20 25
15 -4 24 14
0 -6 16 4
2 15 10 22
30 10 36 20
34 0 40 16
Sample Output
228
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 2e18;
const int MAXN = 1e4+; struct line
{
int le, ri, h;
int id;
bool operator<(const line &a)const{
return h<a.h;
}
}Line[MAXN]; //X用于离散化横坐标,times为此区间被覆盖的次数,block为有多少块子区间, len为被覆盖的长度
int X[MAXN<<], times[MAXN<<], block[MAXN<<], len[MAXN];
bool usedl[MAXN<<], usedr[MAXN<<];
//usedl用于表示区间的左端是否被覆盖, usedr亦如此 void push_up(int u, int l, int r)
{
if(times[u]>) //该区间有被覆盖
{
len[u] = X[r] - X[l];
block[u] = ;
usedl[u] = usedr[u] = true;
}
else //该区间没有被覆盖
{
if(l+==r) //该区间为单位区间
{
len[u] = ;
block[u] = ;
usedl[u] = usedr[u] = false;
}
else //该区间至少包含两个单位区间
{
len[u] = len[u*] + len[u*+];
block[u] = block[u*] + block[u*+];
if(usedr[u*] && usedl[u*+]) //如果左半区间的右端与右半区间的左端均被覆盖,则他们合成一个子区间
block[u]--;
usedl[u] = usedl[u*];
usedr[u] = usedr[u*+];
}
}
} //此种线段树的操作对象为连续型,即最小的元素为长度为1的区间[l,r],其中l和r只代表端点(r-l>=1),用于确定
//区间的位置和长度,l和r本身没有特别的含义。而以往做的什么单点更新之类的,都属于离散型,在l处和r处是有含义的
void add(int u, int l, int r, int x, int y, int v)
{
if(x<=l && r<=y)
{
times[u] += v;
push_up(u, l, r);
return;
} int mid = (l+r)>>;
if(x<=mid-) add(u*, l, mid, x, y, v);
if(y>=mid+) add(u*+, mid, r, x, y, v);
push_up(u, l, r);
} int main()
{
int n;
while(scanf("%d", &n)!=EOF)
{
for(int i = ; i<=n; i++)
{
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
Line[i].le = Line[i+n].le = x1;
Line[i].ri = Line[i+n].ri = x2;
Line[i].h = y1; Line[i+n].h = y2;
Line[i].id = ; Line[i+n].id = -;
X[i] = x1; X[i+n] = x2;
} sort(Line+, Line++*n);
sort(X+, X++*n);
int m = unique(X+, X++*n) - (X+); memset(times, , sizeof(times));
memset(len, , sizeof(len));
memset(block, , sizeof(block));
memset(usedl, false, sizeof(usedl));
memset(usedr, false, sizeof(usedr)); int ans = , pre_len = ;
Line[*n+].h = Line[*n].h; //边界条件
for(int i = ; i<=*n; i++)
{
int l = upper_bound(X+, X++m, Line[i].le) - (X+);
int r = upper_bound(X+, X++m, Line[i].ri) - (X+);
add(, , m, l, r, Line[i].id);
ans += abs(len[] - pre_len); //变化的长度即为显露出来的横向边
ans += *block[]*(Line[i+].h-Line[i].h); //如果有cnt个连续的区间,那么就有2*cnt条显露出来的纵向边
pre_len = len[];
} printf("%d\n", ans);
}
}
POJ1177 Picture —— 求矩形并的周长 线段树 + 扫描线 + 离散化的更多相关文章
- hdu1542 Atlantis (线段树+扫描线+离散化)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]
题意:求矩形面积并 分析:使用线段树+扫描线...因为坐标是浮点数的,因此还需要离散化! 把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用col表示该区间有多少个下边,sum代表该区 ...
- poj 1177 Picture (线段树 扫描线 离散化 矩形周长并)
题目链接 题意:给出n个矩形,每个矩形给左下 和 右上的坐标,求围成的周长的长度. 分析: 首先感谢大神的博客,最近做题经常看大神的博客:http://www.cnblogs.com/kuangbin ...
- POJ 1177 Picture(线段树 扫描线 离散化 求矩形并面积)
题目原网址:http://poj.org/problem?id=1177 题目中文翻译: 解题思路: 总体思路: 1.沿X轴离散化建树 2.按Y值从小到大排序平行与X轴的边,然后顺序处理 如果遇到矩形 ...
- HDU1255 覆盖的面积 —— 求矩形交面积 线段树 + 扫描线 + 离散化
题目链接:https://vjudge.net/problem/HDU-1255 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input输入数据的第一行是一个正整数T(1<= ...
- HDU3642 Get The Treasury —— 求矩形交体积 线段树 + 扫描线 + 离散化
题目链接:https://vjudge.net/problem/HDU-3642 Jack knows that there is a great underground treasury in a ...
- HDU1542 Atlantis —— 求矩形面积并 线段树 + 扫描线 + 离散化
题目链接:https://vjudge.net/problem/HDU-1542 There are several ancient Greek texts that contain descript ...
- hdu 4419 线段树 扫描线 离散化 矩形面积
//离散化 + 扫描线 + 线段树 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层. ...
- HDU 1542 Atlantis(线段树扫描线+离散化求面积的并)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
随机推荐
- java环境配置——jdk8
在官网下载最新版本的jdk 测试版本:jdk-8u60-windows-x64.exe 测试环境:Windows Server 2012 R2 Standard X64 开始执行安装 安装过程中会选 ...
- luogu1494 [国家集训队]小Z的袜子
#include <algorithm> #include <iostream> #include <cstdio> #include <cmath> ...
- Python+selenium登录测试
我们以登录新浪微博为案例来讲解,首先进入登录页面,输入用户名和密码,点击登录按钮,并且获得用户信息以验证是否登录成功. Web地址:https://login.sina.com.cn/signup/s ...
- python 中range和xrange的区别
range() 相当于直接构造一个列表,而xrange() 是返回一个迭代值. range用法: range( 开始值,结束值,步长) 在需要大量迭代的时候,比较适合使用xrange()
- Leetcode 236.二叉树的最近公共祖先
二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x ...
- [POJ2443]Set Operation(bitset)
传送门 题意:给出n个集合(n<=1000),每个集合中最多有10000个数,每个数的范围为1~10000,给出q次询问(q<=200000),每次给出两个数u,v判断是否有一个集合中同时 ...
- POJ3621 Sightseeing Cows【最短路】
题目大意:在一个无向图里找一个环,是的点权和除以边权和最大 思路:UVA11090姊妹题 事实上当这题点权和都为1时就是上一题TUT #include <stdio.h> #include ...
- POJ 1017 Packet
http://poj.org/problem?id=1017 有1*1 2*2...6*6的物品 要装在 6*6的parcel中 问最少用多少个parcel 一直没有找到贪心的策略 问题应该出现在 总 ...
- hdu3622:Bomb Game
给n<=100对点,从每对点里面挑一个并以这些挑出的点为圆心画圆,并且这些圆不能互相覆盖,找出一种方案使得这些圆半径中最小的那个最大. “最小值最大”就是二分答案啦!考虑现在每个点都画出半径x的 ...
- 《effective C++》:条款36——绝不重新定义继承而来的非虚函数
(1)当派生类中重写了基类的非虚函数时,这个时候这个函数发生的是静态绑定 下面中的代码中: 定义一个基类B,基类定义了函数fcm,fcm是非虚的函数. 定义一个派生类D,派生类重新定义了fcm. 当用 ...