博客
关于我
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/

    你可能感兴趣的文章
    Nginx Location配置总结
    查看>>
    Nginx 动静分离与负载均衡的实现
    查看>>
    Nginx 反向代理解决跨域问题
    查看>>
    Nginx 反向代理配置去除前缀
    查看>>
    nginx 后端获取真实ip
    查看>>
    Nginx 学习总结(17)—— 8 个免费开源 Nginx 管理系统,轻松管理 Nginx 站点配置
    查看>>
    nginx 常用配置记录
    查看>>
    Nginx 我们必须知道的那些事
    查看>>
    Nginx 的 proxy_pass 使用简介
    查看>>
    Nginx 的配置文件中的 keepalive 介绍
    查看>>
    nginx 配置 单页面应用的解决方案
    查看>>
    nginx 配置~~~本身就是一个静态资源的服务器
    查看>>
    Nginx下配置codeigniter框架方法
    查看>>
    nginx添加模块与https支持
    查看>>
    Nginx的Rewrite正则表达式,匹配非某单词
    查看>>
    Nginx的使用总结(一)
    查看>>
    Nginx的是什么?干什么用的?
    查看>>
    Nginx访问控制_登陆权限的控制(http_auth_basic_module)
    查看>>
    nginx负载均衡的五种算法
    查看>>
    Nginx配置ssl实现https
    查看>>