题目大意:给若干个矩形,求轮廓边长。

题目分析:与求面积类似。按从下往上扫描,仍然是底边添加,上边删除。但要同时维护竖边的数目,每次扫描对答案的贡献为扫描线上总覆盖长度的变化量加上竖边的增量。总覆盖长度的变化为正说明下轮廓增加,为负以为着碰到了上轮廓增加。

代码如下:

  1. # include<bits/stdc++.h>
  2. using namespace std;
  3. # define mid (l+(r-l)/2)
  4. # define LL long long
  5.  
  6. const int N=5000;
  7.  
  8. struct Segment
  9. {
  10. int x1,x2,y;
  11. int d;
  12. };
  13. struct Node
  14. {
  15. int cnt; ///覆盖的竖线数目
  16. int len; ///被覆盖总长度
  17. int time; ///被覆盖覆盖的次数
  18. bool cl,cr; ///左右端点是否被覆盖
  19. };
  20. Segment seg[N<<1];
  21. Node nde[(N<<4)+5];
  22.  
  23. bool comp(Segment &s1,Segment &s2)
  24. {
  25. return s1.y<s2.y;
  26. }
  27.  
  28. void build(int rt,int l,int r)
  29. {
  30. nde[rt].cnt=0;
  31. nde[rt].len=0;
  32. nde[rt].time=0;
  33. nde[rt].cl=nde[rt].cr=false;
  34. if(l==r) return ;
  35. build(rt<<1,l,mid);
  36. build(rt<<1|1,mid+1,r);
  37. }
  38.  
  39. void pushUp(int rt,int l,int r)
  40. {
  41. if(nde[rt].time>0){
  42. nde[rt].cl=nde[rt].cr=true;
  43. nde[rt].cnt=2;
  44. nde[rt].len=r-l+1;
  45. }else if(l==r){
  46. nde[rt].cl=nde[rt].cr=false;
  47. nde[rt].cnt=0;
  48. nde[rt].len=0;
  49. }else{
  50. nde[rt].cl=nde[rt<<1].cl;
  51. nde[rt].cr=nde[rt<<1|1].cr;
  52. nde[rt].len=nde[rt<<1].len+nde[rt<<1|1].len;
  53. nde[rt].cnt=nde[rt<<1].cnt+nde[rt<<1|1].cnt;
  54. if(nde[rt<<1].cr&&nde[rt<<1|1].cl)
  55. nde[rt].cnt-=2;
  56. }
  57. }
  58.  
  59. void update(int rt,int l,int r,int L,int R,int d)
  60. {
  61. if(L<=l&&r<=R){
  62. nde[rt].time+=d;
  63. pushUp(rt,l,r);
  64. }else{
  65. if(L<=mid) update(rt<<1,l,mid,L,R,d);
  66. if(R>mid) update(rt<<1|1,mid+1,r,L,R,d);
  67. pushUp(rt,l,r);
  68. }
  69. }
  70.  
  71. int main()
  72. {
  73. int n;
  74. while(~scanf("%d",&n))
  75. {
  76. int L=10000,R=-10000;
  77. int x1,y1,x2,y2;
  78. for(int i=0;i<n;++i){
  79. scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
  80. seg[i<<1].x1=seg[i<<1|1].x1=x1,seg[i<<1].y=y1;
  81. seg[i<<1].x2=seg[i<<1|1].x2=x2,seg[i<<1|1].y=y2;
  82. seg[i<<1].d=1;
  83. seg[i<<1|1].d=-1;
  84. L=min(x1,L);
  85. R=max(x2,R);
  86. }
  87. n<<=1;
  88. build(1,L,R-1);
  89. sort(seg,seg+n,comp);
  90. int ans=0;
  91. int last=0;
  92. seg[n].y=seg[n-1].y;
  93. for(int i=0;i<n;++i){
  94. update(1,L,R-1,seg[i].x1,seg[i].x2-1,seg[i].d);
  95. ans+=nde[1].cnt*(seg[i+1].y-seg[i].y);
  96. ans+=abs(nde[1].len-last);
  97. last=nde[1].len;
  98. }
  99. printf("%d\n",ans);
  100. }
  101. return 0;
  102. }

  

HDU-1828 Picture(扫描线)的更多相关文章

  1. 51nod 1206 && hdu 1828 Picture (扫描线+离散化+线段树 矩阵周长并)

    1206 Picture  题目来源: IOI 1998 基准时间限制:2 秒 空间限制:131072 KB 分值: 160 难度:6级算法题  收藏  关注 给出平面上的N个矩形(矩形的边平行于X轴 ...

  2. HDU 1828 Picture(长方形的周长和)

    HDU 1828 Picture 题目链接 题意:给定n个矩形,输出矩形周长并 思路:利用线段树去维护,分别从4个方向扫一次,每次多一段的时候,就查询该段未被覆盖的区间长度,然后周长就加上这个长度,4 ...

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

    Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  4. HDU 1828“Picture”(线段树+扫描线求矩形周长并)

    传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...

  5. hdu 1828 Picture(线段树 || 普通hash标记)

    http://acm.hdu.edu.cn/showproblem.php?pid=1828 Picture Time Limit: 6000/2000 MS (Java/Others)    Mem ...

  6. HDU 1828 Picture (线段树+扫描线)(周长并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1828 给你n个矩形,让你求出总的周长. 类似面积并,面积并是扫描一次,周长并是扫描了两次,x轴一次,y ...

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

    求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的, ...

  8. (中等) HDU 1828 Picture,扫描线。

    Problem Description A number of rectangular posters, photographs and other pictures of the same shap ...

  9. hdu 1828 Picture(线段树扫描线矩形周长并)

    线段树扫描线矩形周长并 #include <iostream> #include <cstdio> #include <algorithm> #include &l ...

  10. hdu 1828 Picture(线段树,扫描线)

    A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wa ...

随机推荐

  1. 编写一个小Servlet程序

    1.编写一个java类,此类继承HttpServlet 创建完工程(见上一篇随笔:使用eclipse创建在myeclipse中运行的web工程),在src中新建一个包,包名字叫servlet:再新建一 ...

  2. 创建和运行shell脚本程序

    转载请标明http://www.cnblogs.com/winifred-tang94/ 要创建一个shell脚本程序,首先新建一个文本文件,然后在这个文本文件中按照shell编程规则输入shell命 ...

  3. eclipse 工程乱码问题

    一 设置工作空间的编码格式(对新建的工程有效) window-->preference-->Gerneral-->Workspace-->Text file coding--- ...

  4. Oracle Data Integrator与OWB的集成及迁移

    v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...

  5. Javascript 基础--数组

    一.一维数组 1.一维数组 var weights = [3,5,1,3.4,2,50]; var all_weight=0; var avg_weight=0; for(var i=0;i<w ...

  6. EditText提示文字

    如图,在没有输入文字前,会显示提醒文字. 引用的是文本文件(strings.xml)中的对应文字 activity_main.xml对应的红色代码: <?xml version="1. ...

  7. php大力力 [016节] 兄弟连高洛峰php教程(2014年 14章数据库章节列表)

    2015-08-25 php大力力016 兄弟连高洛峰php教程(2014年 14章数据库章节列表) [2014]兄弟连高洛峰 PHP教程14.1.1 复习数据库  15:58 [2014]兄弟连高洛 ...

  8. js控制打印 转的

    很多时候,我们在做系统的时候要做打印功能,打印在js中其实很简单,不过这个很简单的代码并不能满足我们的特定需求,比如我们需要打印的表单在很多文字的中间,或者文字中包含一些广告或者图片什么的,这就很难用 ...

  9. hdoj 2059 :龟兔赛跑 (DP)[转]

      转的别人的找了很多就这个比较好理解.   Problem Description 据说在很久很久以前,可怜的兔子经历了人生中最大的打击——赛跑输给乌龟后,心中郁闷,发誓要报仇雪恨,于是躲进了杭州下 ...

  10. javascript的词法分析

    -.arguments的解释: 1.是一个对象,是一个长的很像数组的对象 二.arguments内容是什么? 1.arguments是函数运行时的实参列表 2.arguments收集的“所有”的实参, ...