博客
关于我
Rectangles(2018 ICPC Pacific Northwest Regional Contest F题)
阅读量:388 次
发布时间:2019-03-05

本文共 3896 字,大约阅读时间需要 12 分钟。

给定若干矩形,求被奇数个矩形覆盖到的面积总和。这个问题与传统的矩形覆盖问题不同,传统的问题通常是计算被完全覆盖的区域面积总和,而这里是奇数次覆盖的区域。为了解决这个问题,可以采用线段树和扫描线算法结合懒标记技术。

思路:扫描线

为了处理这个问题,采用扫描线算法,结合线段树和懒标记技术。扫描线算法通过离散化处理,将矩形的左右端点映射到线段树的区间,这样可以高效地处理区间更新和查询操作。

用到的小算法:离散化 + 线段树

  • 离散化:将矩形的左右端点离散化,映射到线段树的区间。
  • 线段树:线段树用于维护区间的有效长度和覆盖次数是否为奇数。每个节点需要维护以下信息:
    • cover:表示区间是否被奇数次覆盖。
    • len:区间在有效覆盖情况下的贡献长度。
  • 懒标记:用于记录需要传递的信息,确保在递归处理时,子树的状态被正确维护。
  • 问题分析

    • 传统的扫描线算法在处理完所有矩形后,总区间的覆盖次数会归零,但在这个问题中,可能存在剩余区间未被覆盖。因此,需要使用懒标记来维护这些区间的状态。
    • 需要处理多个矩形部分重叠的情况,确保懒标记被正确传递,维护子树的状态。

    解决方案

  • 离散化处理:将所有矩形的左右端点离散化,映射到线段树的区间。
  • 线段树构建:构建线段树,每个节点维护区间的有效长度和覆盖次数是否为奇数。
  • 区间更新:使用扫描线算法,递归处理每个矩形的区间,更新线段树中的相关信息,并传递懒标记。
  • 懒标记处理:在递归过程中,处理懒标记,确保子树的状态被正确维护。
  • 代码实现

    import sys
    def main():
    sys.setrecursionlimit(1 << 25)
    n = int(sys.stdin.readline())
    points = []
    lines = []
    for _ in range(n):
    x1, y1, x2, y2 = map(int, sys.stdin.readline().split())
    points.append(x1)
    points.append(x2)
    lines.append((x1, x2, y1, 1))
    lines.append((x1, x2, y2, -1))
    points = sorted(list(set(points)))
    lines = sorted(lines, key=lambda x: (x[0], x[1]))
    len_points = len(points)
    xx = [0] * (2 * n + 1)
    for i in range(2 * n):
    xx[i] = points[i]
    tree = [0] * (4 * len(points))
    for i in range(len(points)):
    tree[i] = {'l': points[i], 'r': points[i], 'len': 0, 'cover': 0}
    def pushup(p):
    if p >= len(tree) or p < 0:
    return
    tree[p]['len'] = tree[left(p)]['len'] + tree[right(p)]['len']
    def down(p, l, r):
    if tree[p]['cover'] == 0:
    return
    mid = (l + r) // 2
    if l == r:
    return
    left_p = left(p)
    right_p = right(p)
    tree[left_p]['cover'] ^= 1
    tree[right_p]['cover'] ^= 1
    len_left = mid - left(p) + 1
    len_right = r - mid
    tree[left_p]['len'] = len_left - tree[left_p]['len']
    tree[right_p]['len'] = len_right - tree[right_p]['len']
    tree[p]['cover'] = 0
    def build(p, l, r):
    if l == r:
    return
    mid = (l + r) // 2
    build(left(p), l, mid)
    build(right(p), mid + 1, r)
    pushup(p)
    def update(p, l, r, f):
    if tree[p]['l'] >= l and tree[p]['r'] <= r:
    tree[p]['cover'] ^= 1
    tree[p]['len'] = (tree[p]['r'] - tree[p]['l'] + 1) - tree[p]['len']
    return
    down(p, tree[p]['l'], tree[p]['r'])
    mid = (tree[p]['l'] + tree[p]['r']) // 2
    if l <= mid:
    update(left(p), l, r, f)
    if r > mid:
    update(right(p), l, r, f)
    pushup(p)
    build(1, 0, len(points) - 1)
    total = 0
    for i in range(2 * n):
    x1, x2, y1, f = lines[i]
    l = 0
    r = len(points) - 1
    while l < r:
    mid = (l + r) // 2
    if lines[i][0] < points[mid]:
    l = mid + 1
    else:
    r = mid
    left_idx = l
    right_idx = r
    if right_idx >= len(points):
    right_idx = len(points) - 1
    while left_idx < right_idx:
    mid = (left_idx + right_idx) // 2
    if points[mid] < x1:
    left_idx = mid + 1
    else:
    right_idx = mid
    left_idx = left_idx if points[left_idx] <= x1 else left_idx + 1
    right_idx = right_idx if points[right_idx] >= x2 else right_idx - 1
    if left_idx >= right_idx:
    continue
    if lines[i][3] == 1:
    y = y1
    else:
    y = y2
    if i == 0:
    h = y - 0
    else:
    h = y - lines[i-1][2]
    total += tree[1]['len'] * h
    update(1, left_idx, right_idx, f)
    print(total)
    if __name__ == "__main__":
    main()

    代码解释

  • 离散化处理:将矩形的左右端点离散化,去重并排序。
  • 线段树构建:每个节点维护区间的有效长度和覆盖次数是否为奇数。
  • 区间更新:递归处理每个矩形的区间,更新线段树中的相关信息,并传递懒标记。
  • 懒标记处理:确保在递归过程中,子树的状态被正确维护,避免重复计算和错误更新。
  • 通过以上步骤,可以高效地计算被奇数次覆盖的区域面积总和。

    转载地址:http://stxwz.baihongyu.com/

    你可能感兴趣的文章
    Netty源码—4.客户端接入流程二
    查看>>
    Netty源码—5.Pipeline和Handler一
    查看>>
    Netty源码—6.ByteBuf原理二
    查看>>
    Netty源码—7.ByteBuf原理三
    查看>>
    Netty源码—7.ByteBuf原理四
    查看>>
    Netty源码—8.编解码原理二
    查看>>
    Netty源码解读
    查看>>
    Netty的Socket编程详解-搭建服务端与客户端并进行数据传输
    查看>>
    Netty相关
    查看>>
    Network Dissection:Quantifying Interpretability of Deep Visual Representations(深层视觉表征的量化解释)
    查看>>
    Network Sniffer and Connection Analyzer
    查看>>
    NetworkX系列教程(11)-graph和其他数据格式转换
    查看>>
    Networkx读取军械调查-ITN综合传输网络?/读取GML文件
    查看>>
    Net与Flex入门
    查看>>
    net包之IPConn
    查看>>
    NFinal学习笔记 02—NFinalBuild
    查看>>
    NFS共享文件系统搭建
    查看>>
    nfs复习
    查看>>
    NFS网络文件系统
    查看>>
    nft文件传输_利用remoting实现文件传输-.NET教程,远程及网络应用
    查看>>