博客
关于我
P1276 校门外的树(增强版) (线段树入门)
阅读量:803 次
发布时间:2019-03-25

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

涉及区间维护的问题,我们通常可以使用线段树来解决。以下是关于该问题的一些详细解释和分析,可能包含一些技术术语,但尽量保持内容容易理解。

我们需要维护一个区间,其中包含一些树木,每一棵树可能有一个或多个树苗。问题要求我们在区间内进行两种操作:一种是种树,另一种是砍树。通过对区间内的树苗和树木数量进行统计和更新,我们的目标是计算最终剩余的树苗数量以及被砍掉的树苗总数。

线段树的结构

为了高效地进行区间更新和查询,我们使用线段树的数据结构。线段树的每个节点表示一个区间,其中包含一些树苗和树木。为了更好地处理区间更新,我们需要为线段树中的每个节点维护更多的信息:

  • tree[rt] 表示该区间内树木的数量。
  • miao[rt] 表示该区间内树苗的数量。
  • tag[rt] 表示该节点的懒标记,用于标记需要在子节点中进行操作的信息。

懒标记的类型包括:

  • 1:表示在该区间内进行种树操作。
  • 2:表示在该区间内进行砍树操作。
  • 3:表示在该区间内进行先砍后种的操作。

需要注意的是,操作3(先砍后种)与操作2(直接砍树)的效果不同,需要在处理时特别注意这一点。

线段树操作

我们需要实现两个主要操作:

  • 种树操作:将区间内的部分区域标记为种树。
  • 砍树操作:从区间内删除树苗和树木。
  • 线段树的每个节点需要维护以下信息:

    • 树苗数量(miao):用于统计区间内的树苗数量。
    • 树木数量(tree):用于统计区间内的树木数量。
    • 懒标记(tag):用于记录必须在子节点中进行的操作。

    代码分析

    以下是提供的代码的详细分析:

    #include 
    using namespace std;#define ll long longconst int maxn = 1e2 + 7;int tree[maxn * 4], miao[MAXN << 2], tag[MAXN << 4];int n, m;int ret = 0;void tree_build(int rt, int l, int r) { if (l == r) { tree[rt] = 1; } else { int mid = (l + r) >> 1; tree_build(rt << 1, l, mid); tree_build(rt << 1 | 1, mid + 1, r); tree[rt] = tree[rt << 1] + tree[rt << 1 | 1]; }}inline void pushdown(int rt, int l, int r) { int mid = (l + r) >> 1; if (tag[rt] == 1) { // 种树操作 miao[rt << 1] = mid - l + 1 - tree[rt << 1]; miao[rt << 1 | 1] = r - mid - tree[rt << 1 | 1]; if (tag[rt << 1] == 2 || tag[rt << 1] == 3) { tag[rt << 1] = 3; } else { tag[rt << 1] = 1; } if (tag[rt << 1 | 1] == 2 || tag[rt << 1 | 1] == 3) { tag[rt << 1 | 1] = 3; } else { tag[rt << 1 | 1] = 1; } } else if (tag[rt] == 2) { // 砍树操作 miao[rt << 1] = 0; miao[rt << 1 | 1] = 0; tree[rt << 1] = 0; tree[rt << 1 | 1] = 0; tag[rt << 1] = 2; tag[rt << 1 | 1] = 2; } else if (tag[rt] == 3) { // 先砍后种操作 tree[rt << 1] = 0; tree[rt << 1 | 1] = 0; miao[rt << 1] = mid - l + 1; miao[rt << 1 | 1] = r - mid; tag[rt << 1] = 3; tag[rt << 1 | 1] = 3; } tag[rt] = 0;}void updata(int rt, int l, int r, int vl, int vr, int v) { if (r < vl || l > vr) { return; } if (vl <= l && r <= vr) { if (v) { // 种树操作 miao[rt] = (r - l + 1) - tree[rt]; if (tag[rt] == 2 || tag[rt] == 3) { tag[rt] = 3; } else { tag[rt] = 1; } } else { // 砍树操作 ret += miao[rt]; tree[rt] = 0; miao[rt] = 0; tag[rt] = 2; } return; } int mid = (l + r) >> 1; pushdown(rt, l, r); updata(rt << 1, l, mid, vl, vr, v); updata(rt << 1 | 1, mid + 1, r, vl, vr, v); tree[rt] = tree[rt << 1] + tree[rt << 1 | 1]; miao[rt] = miao[rt << 1] + miao[rt << 1 | 1];}int main() { scanf("%d %d", &n, &m); tree_build(1, 0, n); while (m--) { int f, x, y; scanf("%d %d %d", &f, &x, &y); updata(1, 0, n, x, y, f); } printf("%d\n%d", miao[1], ret); return 0;}

    代码解析

  • 树结构初始化tree_build 函数递归地从根节点开始构建线段树。对于每个区间,如果该区间的左右边界相等,则该节点是一个叶子节点,树木数量初始化为1。否则,递归地构建左右子树,并合并子树的信息。

  • 懒标记推送pushdown 函数负责将懒标记从父节点推送给子节点。根据懒标记的值(1、2、3),更新子节点的树苗和树木数量,并调整懒标记。

  • 更新操作updata 函数用于执行区间更新操作。根据操作的类型(种树或砍树)和区间的范围,更新节点的信息,并根据懒标记对子节点进行操作。

  • 输入处理和结果输出:在 main 函数中,读取输入数据,执行区间更新操作,最后输出结果。ret 变量记录被砍掉的树苗数量,miao[1]表示根节点所在区间内的树苗数量。

  • 常见问题与注意事项

  • 初始化问题:确保线段树的大小足够容纳所有可能的区间数量,避免数组越界。
  • 懒标记处理:正确传递懒标记至子节点,避免遗漏一些操作,导致错误的数据更新。
  • 函数递归深度:在线段树实现中,递归深度较大时,可能会导致栈溢出,因此需要考虑增加递归深度限制或改为非递归实现。
  • 性能优化:由于线段树的时间复杂度较高,需要优化一些操作,使其在处理大规模数据时更加高效。
  • 总结

    通过上述分析,我们可以看到线段树在区间维护问题中的应用场景。通过合理设计线段树的节点信息和懒标记手法,可以高效地处理较大规模的更新操作。此外,代码的组织结构需要清晰,注释要准确,以便更好地理解和维护代码。

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

    你可能感兴趣的文章
    1Z204050、施工质量不合格的处理
    查看>>
    1Z308020、民事诉讼制度
    查看>>
    JSP中的九大内置对象
    查看>>
    【字节网盘】九款超好看不同页面404源码
    查看>>
    两款404页面自动跳转源码html
    查看>>
    二改广告横幅在线制作源码 美化版
    查看>>
    服饰贴图定制小程序V1.2.4安装更新一体包+小程序前端
    查看>>
    一款好看新颖的404页面源码
    查看>>
    创意沙雕黑色蝙蝠侠/小丑动态404页面源码
    查看>>
    使用Mac OS X如何开启和配置防火墙
    查看>>
    格式化Mac硬盘---DoYourData Super Eraser安全、快速
    查看>>
    MacOS磁盘分区出错的解决办法
    查看>>
    MacOS 应对系统无响应的方法
    查看>>
    使用KeyShot调整一个场景中的照明亮度
    查看>>
    Mac隐藏辅助功能|自定义苹果Mac显示器
    查看>>
    ActivityNotFoundException异常错误
    查看>>
    elasticsearch 不能root启动
    查看>>
    Error merging: refusing to merge unrelated histories
    查看>>
    git远程仓库切换
    查看>>
    国芯网国产芯片精选月刊V20190801 国产芯片 芯片选型 芯片厂家
    查看>>