1 条题解

  • 0
    @ 2025-10-29 20:43:41

    题目分析

    给定一棵 nn 个节点的树,每个节点有一个非负整数权值 GiG_i,进行 qq 次询问,每次询问从节点 xxyy 的路径上选出一个子集,使得子集权值的异或和最大。

    关键观察

    1. 问题本质:在路径上的所有数中选出若干个数,使得异或和最大,这是典型的线性基应用
    2. 树结构:路径唯一,可以使用LCA来分解路径
    3. 数据范围n20000n \leq 20000q200000q \leq 200000,需要高效处理查询

    算法设计

    1. 线性基结构

    维护一个能存储60位数的线性基,支持:

    • 插入一个数
    • 合并两个线性基
    • 查询最大异或和

    2. 树上倍增预处理

    定义以下数组:

    • fa[u][i]fa[u][i]:节点 uu2i2^i 级祖先
    • lb[u][i]lb[u][i]:从 uuuu2i2^i 级祖先路径上所有数的线性基

    3. 预处理步骤

    1. 进行DFS遍历,计算每个节点的深度和直接父亲
    2. 初始化 fa[u][0]fa[u][0]lb[u][0]lb[u][0](只包含 uu 和父节点的权值)
    3. 对于 i=1i = 1MAXLOGMAXLOG
      • fa[u][i]=fa[fa[u][i1]][i1]fa[u][i] = fa[fa[u][i-1]][i-1]
      • lb[u][i]=merge(lb[u][i1],lb[fa[u][i1]][i1])lb[u][i] = merge(lb[u][i-1], lb[fa[u][i-1]][i-1])

    4. 查询处理

    对于查询 (x,y)(x, y)

    1. 计算 lca=LCA(x,y)lca = LCA(x, y)
    2. 分别处理路径 xlcax \to lcaylcay \to lca
      • xx 向上跳到 lcalca,按二进制分解距离,合并对应的线性基
      • yy 向上跳到 lcalca,同样合并线性基
    3. 将两个线性基合并,查询最大异或和

    复杂度分析

    • 预处理O(nlognk2)O(n \log n \cdot k^2),其中 k=60k = 60
    • 每次查询O(lognk2)O(\log n \cdot k^2)
    • 总复杂度O((n+q)lognk2)O((n + q) \log n \cdot k^2),在给定数据范围内可行

    算法优势

    1. 高效查询:通过倍增预处理,将每次查询的复杂度降至 O(logn)O(\log n) 级别
    2. 线性基优化:利用线性基的特性,避免了存储所有路径上的数字
    3. 可扩展性:算法框架清晰,易于实现和调试
    • 1

    信息

    ID
    4676
    时间
    4000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    6
    已通过
    1
    上传者