当前位置:   article > 正文

P5490.扫描线(python)

P5490.扫描线(python)

这个洛谷怎么对于python不太友好呢,没几次能全过的

本题使用扫描线的模板,首先把所有x坐标排序去重,放进列表X中。把所有横线lines排序。这样把所有矩阵都分成了块。对于每一块,高=lines[i+1]-lines[i],宽就等于在这一块中,每个矩阵的并。

比如说图中,纵坐标在3-5之间,那么高度就是2,其中有两块矩阵并起来,计算并起来的宽度=80-10=70,高×宽就是这一块的面积。

所有块的面积之和就是ans。

  1. class node:
  2. def __init__(self, l = None, r = None, cnt = 0, len = 0):
  3. self.l = l
  4. self.r = r
  5. self.cnt = cnt
  6. self.len = len
  7. def build(idx, l, r):
  8. tr[idx] = node(l, r, 0, 0)
  9. if l == r: return
  10. mid = l + r >> 1
  11. build(2*idx, l, mid)
  12. build(2*idx+1, mid+1, r)
  13. def dich(num):
  14. l, r = 0, length-1
  15. while l < r:
  16. mid = l + r >> 1
  17. if X[mid] < num:
  18. l = mid + 1
  19. else:
  20. r = mid
  21. return l
  22. def pushup(idx):
  23. if tr[idx].cnt:
  24. tr[idx].len = X[tr[idx].r+1] - X[tr[idx].l]
  25. else:
  26. try:
  27. tr[idx].len = tr[2*idx].len + tr[2*idx+1].len
  28. except:
  29. tr[idx].len = 0
  30. def modify(idx, l, r, tag):
  31. if tr[idx].l > r or tr[idx].r < l: return
  32. elif l <= tr[idx].l and tr[idx].r <= r:
  33. tr[idx].cnt += tag
  34. pushup(idx)
  35. return
  36. modify(2*idx, l, r, tag)
  37. modify(2*idx+1, l, r, tag)
  38. pushup(idx)
  39. n = int(input())
  40. X = [-float('inf')]
  41. lines = []
  42. # tr中存放所有节点的,l, r, cnt覆盖次数, len覆盖长度
  43. tr = [node()]*(8*n)
  44. ans = 0
  45. for i in range(n):
  46. x1, y1, x2, y2 = map(int, input().split())
  47. X.append(x1)
  48. X.append(x2)
  49. lines.append([y1, x1, x2, 1])
  50. lines.append([y2, x1, x2, -1])
  51. X = sorted(list(set(X)))
  52. length = len(X)
  53. lines.sort()
  54. build(1, 1, length-2)
  55. # 扫描开始
  56. for i in range(len(lines)-1):
  57. y, x1, x2, tag = lines[i]
  58. l = dich(x1)
  59. r = dich(x2)-1
  60. modify(1, l, r, tag)
  61. ans += tr[1].len*(lines[i+1][0] - lines[i][0])
  62. print(ans)

其中需要注意的是,把X排完序,想要从坐标1开始计算,那在X最前面加一个-inf,保证排序从1开始。

又发现X是离散的,所以需要离散化

这样线段树的就以下标为值,例如根节点就是1-5。那么有人就会问为什么不是1-6呢?

如果是1-6,它的左节点就是1-4,右节点就是5-6,我们发现从4到5,实际上差了20,显然不可行。

我们让右左标偏移。

这样右边的5就代表90,左边的1还是代表10。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/592842
推荐阅读
相关标签
  

闽ICP备14008679号