Picture

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3897    Accepted Submission(s): 1978

Problem 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.

 
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.

Please process to the end of file.

 
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

  1. 7
  2. -15 0 5 10
  3. -5 8 20 25
  4. 15 -4 24 14
  5. 0 -6 16 4
  6. 2 15 10 22
  7. 30 10 36 20
  8. 34 0 40 16

Sample Output

  1. 228

First

  1. /*
  2. hdu 1828 线段树扫描线(周长)
  3.  
  4. 给你一些矩阵,有部分or全部重叠.求最终图形的周长
  5.  
  6. 对于x轴的边,矩阵的下边标为1,矩阵的上边标为-1.每次插入后用当前覆盖面积
  7. 减去上一次的覆盖面积(即新增长度),扫描过一个矩阵的上边后便能消除下边的
  8. 影响。
  9. 对x,y轴分别扫描一次即可
  10.  
  11. 最开始没考虑重边的问题,结果C++ AC(G++ WR)
  12. 然后更改后G++才过 - -
  13.  
  14. 2
  15. 0 0 1 1
  16. 1 0 2 1
  17.  
  18. 2
  19. 0 0 1 1
  20. 0 1 1 2
  21.  
  22. hhh-2016-03-26 16:35:21
  23. */
  24. #include <iostream>
  25. #include <cstdio>
  26. #include <cstring>
  27. #include <algorithm>
  28. #include <functional>
  29. using namespace std;
  30. #define lson (i<<1)
  31. #define rson ((i<<1)|1)
  32. typedef long long ll;
  33. const int maxn = 20050;
  34. int a[maxn];
  35. struct node
  36. {
  37. int l,r;
  38. int sum,len;
  39. int mid()
  40. {
  41. return (l+r)>>1;
  42. }
  43. } tree[maxn*5];
  44.  
  45. void push_up(int i)
  46. {
  47. if(tree[i].sum)
  48. tree[i].len = (tree[i].r-tree[i].l+1);
  49. else if(tree[i].l == tree[i].r)
  50. tree[i].len = 0;
  51. else
  52. tree[i].len = tree[lson].len+tree[rson].len;
  53. }
  54.  
  55. void build(int i,int l,int r)
  56. {
  57. tree[i].l = l;
  58. tree[i].r = r;
  59. tree[i].sum = 0;
  60. tree[i].len = 0;
  61. if(l == r)
  62. return ;
  63.  
  64. int mid = tree[i].mid();
  65. build(lson,l,mid);
  66. build(rson,mid+1,r);
  67. push_up(i);
  68. }
  69.  
  70. void push_down(int i)
  71. {
  72. // if(tree[i].sum)
  73. // {
  74. // tree[lson].sum += tree[i].sum;
  75. // tree[rson].sum += tree[i].sum;
  76. // tree[lson].len = tree[lson].r-tree[lson].l;
  77. // tree[rson].len = tree[rson].r-tree[rson].l;
  78. // }
  79. }
  80.  
  81. void Insert(int i,int l,int r,int val)
  82. {
  83. if(tree[i].l >= l && tree[i].r <=r )
  84. {
  85. tree[i].sum += val;
  86. push_up(i);
  87. return ;
  88. }
  89. int mid = tree[i].mid();
  90. push_down(i);
  91. if(l <= mid)
  92. Insert(lson,l,r,val);
  93. if(r > mid)
  94. Insert(rson,l,r,val);
  95. push_up(i);
  96. }
  97.  
  98. struct edge
  99. {
  100. int l,r;
  101. int va,high;
  102. };
  103. edge tx[maxn*2];
  104. edge ty[maxn*2];
  105.  
  106. bool cmp(edge a,edge b)
  107. {
  108. if(a.high != b.high)
  109. return a.high < b.high;
  110. else //如果有重边则要先插入在删除
  111. return a.va > b.va;
  112. }
  113.  
  114. int main()
  115. {
  116. int n;
  117. while(scanf("%d",&n) != EOF)
  118. {
  119. int x1,x2,y1,y2;
  120. int tox = 0,lx=0x3f3f3f3f,rx=0;
  121. int toy = 0,ly=0x3f3f3f3f,ry=0;
  122. for(int i = 1; i <= n; i++)
  123. {
  124. scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
  125. lx = min(x1,lx),rx = max(rx,x2);
  126. ly = min(y1,ly),ry = max(ry,y2);
  127. tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y1,tx[tox++].va=1;
  128. tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y2,tx[tox++].va=-1;
  129. ty[toy].l = y1,ty[toy].r = y2,ty[toy].high=x1,ty[toy++].va=1;
  130. ty[toy].l = y1,ty[toy].r = y2,ty[toy].high=x2,ty[toy++].va=-1;
  131. }
  132. sort(tx,tx+tox,cmp);
  133. sort(ty,ty+toy,cmp);
  134. int ans=0,prelen = 0;
  135. build(1,lx,rx-1);
  136. for(int i = 0; i < tox; i++)
  137. {
  138. Insert(1,tx[i].l,tx[i].r-1,tx[i].va);
  139. ans += abs(tree[1].len-prelen);
  140. prelen = tree[1].len;
  141. }
  142. //cout << ans <<endl;
  143. build(1,ly,ry-1);
  144. prelen = 0;
  145. for(int i = 0; i < toy; i++)
  146. {
  147. Insert(1,ty[i].l,ty[i].r-1,ty[i].va);
  148. ans += abs(tree[1].len-prelen);
  149. prelen = tree[1].len;
  150. }
  151. cout << ans <<endl;
  152. }
  153. return 0;
  154. }

  

Second

  1. /*
  2. hdu 1828 线段树扫描(周长)2
  3.  
  4. 在向上扫描的过程中我们可以计算出平行于x轴的长度
  5. 然后在两条线之间我们只需要计算出有多少条竖线便能得带这两条线之间平行于
  6. y轴的长度。
  7. 用ls和rs来表示当前节点左右端点是否被覆盖
  8. 在处理竖线数量时,注意合并带来的影响,假设lson.rs和rson.ls都存在值的话
  9. 说明存在重叠的部分
  10.  
  11. hhh-2016-03-26 17:58:50
  12. */
  13. #include <iostream>
  14. #include <cstdio>
  15. #include <cstring>
  16. #include <algorithm>
  17. #include <functional>
  18. using namespace std;
  19. #define lson (i<<1)
  20. #define rson ((i<<1)|1)
  21. typedef long long ll;
  22. const int maxn = 20050;
  23. int a[maxn];
  24. struct node
  25. {
  26. int l,r;
  27. int sum,len;
  28. int num,ls,rs;
  29. int mid()
  30. {
  31. return (l+r)>>1;
  32. }
  33. } tree[maxn*5];
  34.  
  35. void push_up(int i)
  36. {
  37. if(tree[i].sum)
  38. {
  39. tree[i].len = (tree[i].r-tree[i].l+1);
  40. tree[i].ls = tree[i].rs = 1;
  41. tree[i].num = 1;
  42. }
  43. else if(tree[i].l == tree[i].r)
  44. {
  45. tree[i].len= 0;
  46. tree[i].num=tree[i].rs=tree[i].ls=0;
  47. }
  48. else
  49. {
  50. tree[i].len = tree[lson].len+tree[rson].len;
  51. tree[i].ls = tree[lson].ls;
  52. tree[i].rs = tree[rson].rs;
  53. tree[i].num = tree[lson].num+tree[rson].num;
  54. tree[i].num -= (tree[lson].rs&tree[rson].ls);
  55. //减去重叠的部分
  56. }
  57. }
  58.  
  59. void build(int i,int l,int r)
  60. {
  61. tree[i].l = l;
  62. tree[i].r = r;
  63. tree[i].sum = tree[i].len = 0;
  64. tree[i].ls = tree[i].rs = tree[i].num = 0;
  65. if(l == r)
  66. return ;
  67.  
  68. int mid = tree[i].mid();
  69. build(lson,l,mid);
  70. build(rson,mid+1,r);
  71. push_up(i);
  72. }
  73.  
  74. void push_down(int i)
  75. {
  76.  
  77. }
  78.  
  79. void Insert(int i,int l,int r,int val)
  80. {
  81. if(tree[i].l >= l && tree[i].r <=r )
  82. {
  83. tree[i].sum += val;
  84. push_up(i);
  85. return ;
  86. }
  87. int mid = tree[i].mid();
  88. push_down(i);
  89. if(l <= mid)
  90. Insert(lson,l,r,val);
  91. if(r > mid)
  92. Insert(rson,l,r,val);
  93. push_up(i);
  94. }
  95.  
  96. struct edge
  97. {
  98. int l,r;
  99. int va,high,id;
  100. };
  101. edge tx[maxn*2];
  102.  
  103. bool cmp(edge a,edge b)
  104. {
  105. if(a.high != b.high)
  106. return a.high < b.high;
  107. else
  108. return a.va > b.va;
  109. }
  110.  
  111. int main()
  112. {
  113. int n;
  114. while(scanf("%d",&n) != EOF)
  115. {
  116. int x1,x2,y1,y2;
  117. int tox = 0,lx=0x3f3f3f3f,rx=0;
  118. for(int i = 1; i <= n; i++)
  119. {
  120. scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
  121. lx = min(x1,lx),rx = max(rx,x2);
  122. tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y1,tx[tox++].va=1;
  123. tx[tox].l = x1,tx[tox].r = x2,tx[tox].high=y2,tx[tox++].va=-1;
  124. }
  125. sort(tx,tx+tox,cmp);
  126. int ans=0,prelen = 0;
  127. build(1,lx,rx-1);
  128. //tx[tox] = tx[tox+1];
  129. for(int i = 0; i < tox; i++)
  130. {
  131. Insert(1,tx[i].l,tx[i].r-1,tx[i].va);
  132. ans += abs(tree[1].len-prelen);
  133. if(i != tox-1)
  134. ans += (tx[i+1].high-tx[i].high)*tree[1].num*2;
  135. prelen = tree[1].len;
  136. }
  137. cout << ans <<endl;
  138. }
  139. return 0;
  140. }

  

hdu 1828 线段树扫描线(周长)的更多相关文章

  1. HDU 1828 线段树+扫描线(计算矩形周长并)

    题意:给你n个矩形,然后矩形有可能重叠,要你求周长 思路:首先碰到这种矩形在数轴上那么第一反应应该想到的是扫描线, 做周长我们有两种方法 第一种,我们可以分开两部分求,第一遍求x轴上的贡献,第二遍求y ...

  2. hdu 4052 线段树扫描线、奇特处理

    Adding New Machine Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  3. hdu 5091(线段树+扫描线)

    上海邀请赛的一道题目,看比赛时很多队伍水过去了,当时还想了好久却没有发现这题有什么水题的性质,原来是道成题. 最近学习了下线段树扫描线才发现确实是挺水的一道题. hdu5091 #include &l ...

  4. HDU 5107 线段树扫描线

    给出N个点(x,y).每一个点有一个高度h 给出M次询问.问在(x,y)范围内第k小的高度是多少,没有输出-1 (k<=10) 线段树扫描线 首先离散化Y坐标,以Y坐标建立线段树 对全部的点和询 ...

  5. hdu 1542 线段树+扫描线 学习

    学习扫描线ing... 玄学的东西... 扫描线其实就是用一条假想的线去扫描一堆矩形,借以求出他们的面积或周长(这一篇是面积,下一篇是周长) 扫描线求面积的主要思想就是对一个二维的矩形的某一维上建立一 ...

  6. hdu 1255(线段树 扫描线) 覆盖的面积

    http://acm.hdu.edu.cn/showproblem.php?pid=1255 典型线段树辅助扫描线,顾名思义扫描线就是相当于yy出一条直线从左到右(也可以从上到下)扫描过去,此时先将所 ...

  7. HDU 5091 线段树扫描线

    给出N个点.和一个w*h的矩形 给出N个点的坐标,求该矩形最多能够覆盖多少个点 对每一个点point(x.y)右边生成相应的点(x+w,y)值为-1: 纵向建立线段树,从左到右扫描线扫一遍.遇到点则用 ...

  8. hdu 4419 线段树 扫描线 离散化 矩形面积

    //离散化 + 扫描线 + 线段树 //这个线段树跟平常不太一样的地方在于记录了区间两个信息,len[i]表示颜色为i的被覆盖的长度为len[i], num[i]表示颜色i 『完全』覆盖了该区间几层. ...

  9. hdu 3265 线段树扫描线(拆分矩形)

    题意:        给你n个矩形,每个矩形上都有一个矩形的空洞,所有的矩形都是平行于x,y轴的,最后问所有矩形的覆盖面积是多少. 思路:       是典型的矩形覆盖问题,只不过每个矩形上多了一个矩 ...

随机推荐

  1. 在arc模式下 CGImage 释放问题

    //大图bigImage //定义myImageRect,截图的区域 if (imagecount >= 3) { CGRect myImageRect; if (i.size.width< ...

  2. java unicode和字符串间的转换

    package ykxw.web.jyf; /** * Created by jyf on 2017/5/16. */ public class unicode { public static voi ...

  3. cord-in-a-box 2.0 安装指南

    [TOC] 这篇文章简要介绍了 Ciab2.0 的安装. 包括硬件, 软件环境的选择, Ciab2.0的实际部署架构, 安装过程等. 下面就先对 Ciab2.0 部署环境做简要介绍. 1. 概述 这一 ...

  4. 关于网页设计的css+html相对定位和决定定位的理解

    css中有很多定位,其中最重要的是相对定位和绝对定位: 定位很重要,不搞好,网页就会很乱,显示的完全不是自己想要的效果,自己必须掌握: 首先说一个重要的结论:绝对定位,是不占位置的,总是相对离自己最近 ...

  5. python 中 reduce 函数的使用

    reduce()函数也是Python内置的一个高阶函数. reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接 ...

  6. python中 return 的用法

    return 语句就是讲结果返回到调用的地方,并把程序的控制权一起返回 程序运行到所遇到的第一个return即返回(退出def块),不会再运行第二个return. 要返回两个数值,写成一行即可: de ...

  7. 官网jquery压缩版引用地址:

    3.1.1版本 <!DOCTYPE html> <html lang="en"> <head> <meta charset="U ...

  8. 用于水和水蒸汽物性计算的Python模块——iapws

    无论是火电还是核电,将能量转化为电能的方式主要还是烧开水,即加热水产生高压蒸汽驱动汽轮机做功再发电.在进行热力循环分析.流动传热计算时,需获得水和水蒸汽的物性参数.网上主流的水蒸汽物性计算程序是上海成 ...

  9. 单源最短路径---Bellman-Ford算法

    传送门: Dijkstra Bellman-Ford SPFA Floyd 1.Dijkstra算法的局限性 像上图,如果用dijkstra算法的话就会出错,因为如果从1开始,第一步dist[2] = ...

  10. JS面向对象之原型链

      对象的原型链 只要是对象就有原型 原型也是对象 只要是对象就有原型, 并且原型也是对象, 因此只要定义了一个对象, 那么就可以找到他的原型, 如此反复, 就可以构成一个对象的序列, 这个结构就被成 ...