[POJ1177]Picture

试题描述

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 union of all rectangles is called the perimeter.

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.

输入

Your program is to read from standard input. The first line contains the number of rectangles pasted on the wall. In each of the subsequent lines, one can find the integer coordinates of the lower left vertex and the upper right vertex of each rectangle. The values of those coordinates are given as ordered pairs consisting of an x-coordinate followed by a y-coordinate.

0 <= number of rectangles < 5000 
All coordinates are in the range [-10000,10000] and any existing rectangle has a positive area.

输出

Your program is to write to standard output. The output must contain a single line with a non-negative integer which corresponds to the perimeter for the input rectangles.

输入示例

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

输出示例

228

数据规模及约定

见“输入

题解

可以发现水平方向的边与竖直方向的边是独立的,那么我们可以分别做两次扫描线。

不难发现扫描线运行时要进行区间修改操作,所以会想到线段树。会发现单纯地打懒标记像一般的题那样做是不行的,这里引入一个新的维护方法,在这里,我们不用标记下传;每次区间的修加就是对对应区间的节点打上一个标记,区间删就是对对应区间的节点回收那个标记,标记是静态的,不能下传。

显然对答案的贡献一定是在某个矩形的上下边界时产生的,也就是说只用在扫描线扫到需要加或需要删的操作时才累计答案。对于加操作,我们计加之后与加之前相差为 t,那么把答案累加 t;删操作同理。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;

int read() {
	int x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); }
	return x * f;
}

#define maxn 20010
#define maxr 5010
int n;
struct Rec {
	int x1, y1, x2, y2;
	Rec() {}
	Rec(int _1, int _2, int _3, int _4): x1(_1), y1(_2), x2(_3), y2(_4) {}
} rs[maxr];
struct Line {
	int l, r, x;
	Line() {}
	Line(int _1, int _2, int _3): l(_1), r(_2), x(_3) {}
	bool operator < (const Line& t) const { return x < t.x; }
} ad[maxr], mi[maxr];
int ca, cm, ans;

int cntv[maxn<<2], sumv[maxn<<2];
void update(int L, int R, int o, int ql, int qr, int v) {
	int M = L + R >> 1, lc = o << 1, rc = lc | 1;
	if(ql <= L && R <= qr) {
		cntv[o] += v;
		if(cntv[o]) sumv[o] = R - L + 1;
		else if(L == R) sumv[o] = 0;
		else sumv[o] = sumv[lc] + sumv[rc];
		return ;
	}
	if(ql <= M) update(L, M, lc, ql, qr, v);
	if(qr > M) update(M+1, R, rc, ql, qr, v);
	sumv[o] = cntv[o] ? R - L + 1 : sumv[lc] + sumv[rc];
	return ;
}

void solve() {
	sort(ad + 1, ad + ca + 1);
	sort(mi + 1, mi + ca + 1);
	memset(sumv, 0, sizeof(sumv));
	memset(cntv, 0, sizeof(cntv));
	int ka = 1, km = 1;
	for(int i = 1; i <= 20001; i++) {
		while(ka <= ca && ad[ka].x == i) {
			int tmp = sumv[1];
			update(1, 20001, 1, ad[ka].l, ad[ka].r - 1, 1);
			ans += sumv[1] - tmp;
//			printf("add[%d, %d]: %d <- %d\n", ad[ka].l, ad[ka].r - 1, sumv[1], tmp);
			ka++;
		}
		while(km <= cm && mi[km].x == i) {
			int tmp = sumv[1];
			update(1, 20001, 1, mi[km].l, mi[km].r - 1, -1);
			ans += tmp - sumv[1];
//			printf("del[%d, %d]: %d <- %d\n", mi[km].l, mi[km].r - 1, sumv[1], tmp);
			km++;
		}
	}
	return ;
}

int main() {
	n = read();
	for(int i = 1; i <= n; i++) {
		int x1 = read() + 10001, y1 = read() + 10001, x2 = read() + 10001, y2 = read() + 10001;
		rs[i] = Rec(x1, y1, x2, y2);
		ad[++ca] = Line(y1, y2, x1);
		mi[++cm] = Line(y1, y2, x2);
	}

	solve();
	ca = cm = 0;
	for(int i = 1; i <= n; i++) {
		int x1 = rs[i].x1, x2 = rs[i].x2, y1 = rs[i].y1, y2 = rs[i].y2;
		ad[++ca] = Line(x1, x2, y1);
		mi[++cm] = Line(x1, x2, y2);
	}
	solve();

	printf("%d\n", ans);

	return 0;
}
时间: 2024-10-19 17:46:58

[POJ1177]Picture的相关文章

poj-1177 Picture(矩形周长并,线段树+扫描线)

题目链接:点击打开链接 Picture Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 11706   Accepted: 6175 Description A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical o

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,就是给出图形中间的小矩

【poj1177】 Picture

http://poj.org/problem?id=1177 (题目链接) 题意 求矩形周长并. Solution 转自:http://www.cnblogs.com/Booble/archive/2010/10/10/1847163.html 先看图: 为了解决这个问题 我们先把一坨一坨的矩形 进行矩形切割: 我们考虑周长由哪些部分构成 其中,红线是需要统计入周长的竖边,绿线是需要统计入周长的横边 我们称两条蓝线之间的部分为统计区间 我们需要依次统计从左到右的统计区间内的需要计数的矩形边,累加

Picture poj1177

Picture Time Limit: 2000MS   Memory Limit: 10000K Total Submissions: 12265   Accepted: 6484 Description 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

【HDOJ1828&amp;&amp;POJ1177】Picture(线段树,扫描线)

题意:给定n个矩形,求他们的并的周长 n<=5e3,abs(x[i])<=1e4 思路:From https://www.cnblogs.com/kuangbin/archive/2013/04/10/3013437.html 真实"线段"树 1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #include<cmath> 5 #include<ios

HDU 1828 Picture(矩形周长并)

HDU 1828 Picture 题目链接 题意:给定n个矩形,输出矩形周长并 思路:利用线段树去维护,分别从4个方向扫一次,每次多一段的时候,就查询该段未被覆盖的区间长度,然后周长就加上这个长度,4个方向都加完就是答案 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 5005; int n; struct Rec { int

usaco Picture

/* ID: modengd1 PROG: picture LANG: C++ */ #include <iostream> #include <stdio.h> #include <memory.h> #include <vector> #include <algorithm> using namespace std; int N; struct edge { int y,x1,x2; bool isbegin; bool friend ope

Hole puncher Show Picture

import sys reload(sys) sys.setdefaultencoding('utf8') import matplotlib.pyplot as plt import string file = open("GD.txt") i = 0 x = range(0) y = range(0) for line in file: x.append(string.atoi(line[0:7], 10)) y.append(string.atoi(line[8:], 10))

杭电1162--Eddy&#39;s picture(Prim()算法)

Eddy's picture Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8070    Accepted Submission(s): 4084 Problem Description Eddy begins to like painting pictures recently ,he is sure of himself to b