POJ 1177:Picture(线段树-扫描线)
来源:互联网 发布:python最经典的书籍 编辑:程序博客网 时间:2024/05/16 15:29
Picture
Time Limit: 2000MS Memory Limit: 10000KTotal Submissions: 11857 Accepted: 6259
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. 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.
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
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.
0 <= number of rectangles < 5000
All coordinates are in the range [-10000,10000] and any existing rectangle has a positive area.
Output
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.
Sample Input
7-15 0 5 10-5 8 20 2515 -4 24 140 -6 16 42 15 10 2230 10 36 2034 0 40 16
Sample Output
228
Source
IOI 1998
(x轴)扫描线:沿x轴从左到右的一条条垂直于x轴的线段(一个矩形两条扫描线)每个扫描线存储四个信息:
扫描线所在x坐标、扫描线上端和下端y坐标、扫描线是入边还是出边(在同一个矩形的左边还是右边)
解题方法:用线段树做,线段树存储的是y轴的覆盖情况,先将y轴出现的坐标离散化,若离散化后得出k个不同的
点,线段树就有k-1个叶子,每个叶子表示相邻两点之间的那段距离。每个节点存储5个信息:当前节点被覆盖的长
度、当前节点至少被完全覆盖多少次(这个没必要下放)、当前节点的最左端和最右段分别是否被覆盖和当前节点
有多少个不连续的覆盖区域。初始化所有节点所有变量为0,然后从左到右遍历每个扫描线,依次更新并求出相邻
两条扫描线之间的周长(有些题会是求面积),周长包括竖边和横边,其中竖边长为|更新后线段树总覆盖区域-
更新前线段树总覆盖区域|,横边总长为更新前不连续覆盖区域个数×(相邻扫描线的x坐标差)
#include<stdio.h>#include<math.h>#include<string.h>#include<algorithm>using namespace std;typedef struct /*扫描线*/{int x;int h, d;int flag;}Square;typedef struct /*线段树节点*/{int line;int lc, rc;int cnt;int s1;}Point;Point tre[88888], temp;Square s[11015];int pos[11015];void Update(int l, int r, int x, int a, int b, int t);/*更新*/void Atonce(int l, int r, int x);int Bsech(int l, int r, int k)/*通过二分搜索找到坐标对应离散化后的点*/{int m;m = (l+r)/2;if(pos[m]<k)return Bsech(m+1, r, k);if(pos[m]>k)return Bsech(l, m-1, k);return m;}bool comp(Square a, Square b){if(a.x<b.x || a.x==b.x && a.flag==1 && b.flag==-1)/*注意:如果某个入边和某个出边的x坐标相等,入边一定要排在那个出边前面*/return 1;return 0;}int main(void){int i, n, x1, y1, x2, y2, len, sum;while(scanf("%d", &n)!=EOF){len = 1;sum = 0;memset(tre, 0, sizeof(tre));for(i=1;i<=n;i++){scanf("%d%d%d%d", &x1, &y1, &x2, &y2);s[i*2-1].x = x1, s[i*2].x = x2;s[i*2-1].h = s[i*2].h = y2;s[i*2-1].d = s[i*2].d = y1;s[i*2-1].flag = 1, s[i*2].flag = -1;pos[i*2-1] = y1, pos[i*2] = y2;}n = n*2;sort(s+1, s+n+1, comp);sort(pos+1, pos+n+1);for(i=2;i<=n;i++){if(pos[i]!=pos[i-1])pos[++len] = pos[i];}for(i=1;i<=n;i++){x1 = Bsech(1, len, s[i].d);x2 = Bsech(1, len, s[i].h);temp = tre[1];Update(1, len-1, 1, x1, x2-1, s[i].flag);/*更新区间x1和x2-1, s[i].flag表示应该添加还是删除该段*/sum += abs(tre[1].s1-temp.s1)+temp.line*2*(s[i].x-s[i-1].x);}printf("%d\n", sum);}return 0;}void Update(int l, int r, int x, int a, int b, int t){int m;if(l>=a && r<=b){tre[x].cnt += t;Atonce(l, r, x);return;}m = (l+r)/2;if(a<=m)Update(l, m, x*2, a, b, t);if(b>=m+1)Update(m+1, r, x*2+1, a, b, t);Atonce(l, r, x);}void Atonce(int l, int r, int x){if(tre[x].cnt>=1)/*如果当前节点至少被完全覆盖1次或以上*/tre[x].s1 = pos[r+1]-pos[l], tre[x].line = 1, tre[x].lc = tre[x].rc = 1;elsetre[x].s1 = tre[x*2].s1+tre[x*2+1].s1, tre[x].line = 0, tre[x].lc = tre[x].rc = 0;if(tre[x].cnt==0 && l!=r){if(tre[x*2].lc==1)tre[x].lc = 1;if(tre[x*2+1].rc==1)tre[x].rc = 1;tre[x].line = tre[x*2].line+tre[x*2+1].line;/*当前节点不连续覆盖区域的个数等于两个儿子不连续覆盖区域的个数之和*/if(tre[x*2].rc==1 && tre[x*2+1].lc==1)/*当然如果左儿子的右端和右儿子的左端连续,那么当前节点不连续覆盖区域的个数就要-1*/tre[x].line--;}}
1 0
- POJ 1177 Picture (线段树扫描线)
- poj - 1177 - Picture(离线化+扫描线+线段树)
- POJ 1177 Picture(线段树+扫描线)
- POJ 1177:Picture(线段树-扫描线)
- POJ 1177-Picture(线段树+离散化+扫描线)
- poj 1177 Picture 线段树+离散化+线扫描
- POJ 1177 Picture (线段树+离散化+扫描线) 详解
- picture 1177 poj 线段树+扫描线+离散化
- 【线段树+扫描线】 HDOJ 1828 && POJ 1177 Picture
- POJ 1177 Picture [离散化+扫描线+线段树]
- POJ - 1177 Picture(线段树 扫描线 区间合并)
- poj 1177 Picture 【线段树 扫描线 求轮廓周长】
- POJ 1177&&HDU1828 Picture 线段树+扫描线
- HDU 1828 && POJ 1177 Picture(线段树+扫描线+离散化)
- poj 1177 || HDU 1828 Picture (线段树扫描线求 图形并的周长)
- poj-1177 Picture(矩形周长并,线段树+扫描线)
- poj 1177 picture(线段树+扫描线+离散化)★
- POJ 1177 Picture & hdu 1828 Picture(扫描线)
- 黑苹果,Mac OS X如何使用USB数据线连接手机网络(没有网卡驱动时)
- 前后端分离的思考与实践(一)
- vs2010,2013c++代码格式化
- 324. Wiggle Sort II
- Spark Streaming 订单关联案例剖析
- POJ 1177:Picture(线段树-扫描线)
- Cucumber+java
- 自定义内存复制函数memcpy()
- Spring基础知识
- XML数据格式原生解析器
- EXP-00091: Exporting questionable statistics.
- 二叉搜索树的第K个结点
- 【p3】·python文件读取·数据存储(pigeon详细说)
- 杭电 ACM 1015 --Safecracker