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

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

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

思路:扫描线

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

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

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

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

    解决方案

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

    import sysdef 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/

    你可能感兴趣的文章
    No Datastore Session bound to thread, and configuration does not allow creation of non-transactional
    查看>>
    No fallbackFactory instance of type class com.ruoyi---SpringCloud Alibaba_若依微服务框架改造---工作笔记005
    查看>>
    No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalanc
    查看>>
    No mapping found for HTTP request with URI [/...] in DispatcherServlet with name ...的解决方法
    查看>>
    No mapping found for HTTP request with URI [/logout.do] in DispatcherServlet with name 'springmvc'
    查看>>
    No module named 'crispy_forms'等使用pycharm开发
    查看>>
    No module named cv2
    查看>>
    No module named tensorboard.main在安装tensorboardX的时候遇到的问题
    查看>>
    No module named ‘MySQLdb‘错误解决No module named ‘MySQLdb‘错误解决
    查看>>
    No new migrations found. Your system is up-to-date.
    查看>>
    No qualifying bean of type XXX found for dependency XXX.
    查看>>
    No resource identifier found for attribute 'srcCompat' in package的解决办法
    查看>>
    no session found for current thread
    查看>>
    No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android
    查看>>
    NO.23 ZenTaoPHP目录结构
    查看>>
    NO32 网络层次及OSI7层模型--TCP三次握手四次断开--子网划分
    查看>>
    NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
    查看>>
    Node JS: < 一> 初识Node JS
    查看>>
    Node-RED中使用JSON数据建立web网站
    查看>>
    Node-RED中使用json节点解析JSON数据
    查看>>