题目链接

题意

给出n个矩形,求周长并。

思路

学了区间并,比较容易想到周长并。

我是对x方向和y方向分别做两次扫描线。应该记录一个pre变量,记录上一次扫描的时候的长度,对于每次遇到扫描线统计答案的时候,使用当前的 tree[1] 去与 pre 做相减,因为这一次如果边长增加了或者减少了,那么一定和之前的值有差值,其中的差值就是这次的变化量。

但是这份代码交G++会WA,C++就A了。而且排序的时候如果权值相同,应该让状态为1(开始)的扫描线排在状态为-1(结束)的扫描线前面,因为重合的话,那个边长不可计算到答案里面的。如果先更新结束的,代表这一段边长(如果更新之后消失了的话)会导致算上这一部分的贡献,然后又更新开始的,又算上一次这一部分的贡献,等于算上了两次。然而真实情况下,是不应该算上这部分的贡献的。

这题不用离散化也可以,习惯性。

  1. #include <cstdio>
  2. #include <cmath>
  3. #include <algorithm>
  4. #include <cstring>
  5. using namespace std;
  6. const int INF = 0x3f3f3f3f;
  7. const int N = 2e4 + 10;
  8. #define lson l, m, rt<<1
  9. #define rson m + 1, r, rt<<1|1
  10. typedef long long LL;
  11. struct Node {
  12. int l, r, w, st;
  13. Node () {}
  14. Node (int _l, int _r, int _w, int _st) {
  15. l = _l, r = _r, w = _w, st = _st;
  16. }
  17. bool operator < (const Node &rhs) const {
  18. if(w == rhs.w) return st > rhs.st; // 开始在结束前面
  19. return w < rhs.w;
  20. }
  21. } px[N], py[N];
  22. int tree[N<<2], cnt[N<<2];
  23. int x[N], y[N];
  24. void pushup(int l, int r, int rt, int *axis) {
  25. if(cnt[rt] > 0) tree[rt] = axis[r+1] - axis[l];
  26. else if(l == r) tree[rt] = 0;
  27. else tree[rt] = tree[rt<<1] + tree[rt<<1|1];
  28. }
  29. void update(int L, int R, int w, int l, int r, int rt, int *axis) {
  30. if(L <= l && r <= R) {
  31. cnt[rt] += w;
  32. pushup(l, r, rt, axis);
  33. return ;
  34. }
  35. int m = (l + r) >> 1;
  36. if(L <= m) update(L, R, w, lson, axis);
  37. if(m < R) update(L, R, w, rson, axis);
  38. pushup(l, r, rt, axis);
  39. }
  40. int solve(int n, int *axis, Node *p, int ct) {
  41. memset(tree, 0, sizeof(tree));
  42. memset(cnt, 0, sizeof(cnt));
  43. int ans = 0, pre = 0;
  44. for(int i = 1; i <= n; i++) {
  45. int L = lower_bound(axis + 1, axis + 1 + ct, p[i].l) - axis;
  46. int R = lower_bound(axis + 1, axis + 1 + ct, p[i].r) - axis - 1;
  47. update(L, R, p[i].st, 1, ct, 1, axis);
  48. ans += abs(tree[1] - pre);
  49. pre = tree[1];
  50. }
  51. return ans;
  52. }
  53. int main() {
  54. int n;
  55. while(~scanf("%d", &n)) {
  56. int cntx = 0, cnty = 0;
  57. for(int i = 1; i <= n; i++) {
  58. int x1, x2, y1, y2;
  59. scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
  60. x[++cntx] = x1; x[++cntx] = x2;
  61. y[++cnty] = y1; y[++cnty] = y2;
  62. px[i*2-1] = Node(y1, y2, x1, 1);
  63. px[i*2] = Node(y1, y2, x2, -1);
  64. py[i*2-1] = Node(x1, x2, y1, 1);
  65. py[i*2] = Node(x1, x2, y2, -1);
  66. }
  67. sort(x + 1, x + 1 + cntx);
  68. sort(y + 1, y + 1 + cnty);
  69. cntx = unique(x + 1, x + 1 + cntx) - x - 1;
  70. cnty = unique(y + 1, y + 1 + cnty) - y - 1;
  71. int m = 2 * n;
  72. sort(px + 1, px + 1 + m);
  73. sort(py + 1, py + 1 + m);
  74. int ans = solve(m, x, py, cntx) + solve(m, y, px, cnty);
  75. printf("%d\n", ans);
  76. }
  77. return 0;
  78. }
  79. /*
  80. 7
  81. -15 0 5 10
  82. -5 8 20 25
  83. 15 -4 24 14
  84. 0 -6 16 4
  85. 2 15 10 22
  86. 30 10 36 20
  87. 34 0 40 16
  88. */

HDU 1828:Picture(扫描线+线段树 矩形周长并)的更多相关文章

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

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

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

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

  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(线段树,扫描线)

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

  5. luogu P1856 [USACO5.5]矩形周长Picture 扫描线 + 线段树

    Code: #include<bits/stdc++.h> #define maxn 200007 #define inf 100005 using namespace std; void ...

  6. HDU 1542:Atlantis(扫描线+线段树 矩形面积并)***

    题目链接 题意 给出n个矩形,求面积并. 思路 使用扫描线,我这里离散化y轴,按照x坐标从左往右扫过去.离散化后的y轴可以用线段树维护整个y上面的线段总长度,当碰到扫描线的时候,就可以统计面积.这里要 ...

  7. hdu1828(线段树——矩形周长并)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1828 分析:与面积不同的地方是还要记录竖的边有几个(num记录),并且当边界重合的时候需要合并(用lb ...

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

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

  9. poj 1151 Atlantis (离散化 + 扫描线 + 线段树 矩形面积并)

    题目链接题意:给定n个矩形,求面积并,分别给矩形左上角的坐标和右上角的坐标. 分析: 映射到y轴,并且记录下每个的y坐标,并对y坐标进行离散. 然后按照x从左向右扫描. #include <io ...

随机推荐

  1. QRCode二维码生成方案及其在带LOGO型二维码中的应用(2)

    原文:QRCode二维码生成方案及其在带LOGO型二维码中的应用(2) 续前:QRCode二维码生成方案及其在带LOGO型二维码中的应用(1)  http://blog.csdn.net/johnsu ...

  2. js 注册事件

    <!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...

  3. 【C#】WindowsAPICodePack-Shell使用教程

    原文:[C#]WindowsAPICodePack-Shell使用教程 1.首先在项目中添加WindowsAPICodePack的Nuget包.   点击安装即可. 2.获取<我的电脑>的 ...

  4. __declspec的15种用法

    __cdecl和__stdcall都是函数调用规范(还有一个__fastcall),规定了参数出入栈的顺序和方法,如果只用VC编程的话可以不用关心,但是要在C++和Pascal等其他语言通信的时候就要 ...

  5. Win10如何设置开机自动登录

    原文:Win10如何设置开机自动登录 第一步: 小娜搜索"netplwiz",进入用户账户设置. 第二步: 先勾选选中一次,要使用本计算机,用户必须输入用户名和密码. 第三步: 取 ...

  6. CenOS7 docker部署lnmp环境

    Step1:下载lnmp镜像 [root@docker html]# docker pull winstonpro/lnmp Step2:启动lnmp镜像的docker实例 [root@docker ...

  7. Linux杂谈: 树形显示多级目录--tree

    最近写博客的时候偶尔会需要将文件目录结构直观地列出来,例如python的包结构. 于是在网上搜了搜,发现了一个Linux下还不错的工具--tree tree 可以很直观地显示多级目录结构. 1. 安装 ...

  8. 2015元旦第一弹——WP8.1应用程序栏(C#后台代码编写)

    //第一次写博文,以后还请各位道友互相关照哈.废话不多说,直接进入正题. 相信大家对于如何在XAML添加应用程序栏应该很清楚,不清楚的话,可以打开新建个Pviot应用 就有系统自带的菜单栏. 本文主要 ...

  9. Mono 4.0 发布,开源跨平台 .Net 框架

    快速使用Romanysoft LAB的技术实现 HTML 开发Mac OS App,并销售到苹果应用商店中.   <HTML开发Mac OS App 视频教程> 土豆网同步更新:http: ...

  10. AnmpServer 0.9.3 发布

    摘要: AnmpServer是一款集成Apache服务器.Nginx服务器.MySQL数据库.PHP解释器的整合软件包.免去了开发人员将时间花费在繁琐的配置环境过程,从而腾出更多精力去做开发,助力PH ...