1 条题解

  • 0
    @ 2025-11-30 23:21:49

    题意理解

    我们有一棵有根树(根为 1),每条边上有一个字符 01
    定义 SuS_u 为从根到 uu 路径上所有边的字符连接成的字符串。

    扩展点:如果 SuS_uSvS_v 的后缀,则 vvuu 的扩展点。

    每个点 uu 有:

    • valuval_u:价值
    • aua_u:限制

    过程

    1. Alice 从 SuS_u 删除末尾 ii 个字符,得到 SS'(长度 iiSu|S_u|00)。
    2. Bob 收到 SS',可以在末尾加字符得到 SS''
    3. 如果存在 uu 的扩展点 vv 使得:
      • S=SvS'' = S_v
      • Sav|S'| \ge a_v 则 Bob 获得 valvval_v,且 Bob 会选择 最大valvval_v
    4. 对每个 ii 得到最大收益,求和就是 ansuans_u

    形式化转化

    对每个 uu,求: $ ans_u = \sum_{i=0}^{|S_u|} \max_{\substack{i \ge a_v \\ S_u = S_v[|S_v|-|S_u|+1, |S_v|] \\ S_u[1, i] = S_v[1, i]}} val_v $ 其中 Ext(u)\text{Ext}(u)uu 的扩展点集合。


    关键观察

    1. 扩展点的含义
      vvuu 的扩展点 ⇔ SuS_uSvS_v 的后缀 ⇔ 在 后缀树/后缀自动机 上,uu 对应的节点是 vv 对应节点的祖先(在反串的 suffix tree 中),但更简单的是:
      Trie 上(所有 SuS_u 插入 Trie),uu 对应的节点是 vv 对应节点的祖先(因为 SuS_uSvS_v 的前缀?注意这里方向反了)。

      实际上 SuS_uSvS_v 的后缀 ⇔ 在正串的 Trie 上,uuvv 的祖先?不,这是前缀关系。
      后缀关系需要反转字符串:定义 Tu=reverse(Su)T_u = \text{reverse}(S_u),那么 SuS_uSvS_v 的后缀 ⇔ TuT_uTvT_v 的前缀。

      所以我们可以把每个 SuS_u 反转,插入 Trie,那么扩展点关系就是 Trie 上的 祖先-后代 关系。

    2. 条件 Su[1,i]=Sv[1,i]S_u[1,i] = S_v[1,i]
      在反转串的 Trie 中,Su[1,i]S_u[1,i] 对应 TuT_u 的前 ii 个字符,也就是原串 SuS_u 的后 ii 个字符反转。
      但更简单理解:ii 是 Alice 删除后剩下的长度,Su[1,i]S_u[1,i]SuS_u 的前缀,Sv[1,i]S_v[1,i]SvS_v 的前缀,要求它们相等。
      在 Trie 上(正串),前缀相等意味着它们有公共祖先在深度 ii 处。

      所以我们可以:

      • 将所有 SuS_u 插入 Trie,每个节点对应一个前缀。
      • 对每个 uu,在 Trie 上从根到 uu 的路径上(深度 dd 从 0 到 Su|S_u|),我们考虑深度 ii 的节点 pp,我们要找 uu 的扩展点 vvvvpp 的子树中(因为 SvS_v 的前 ii 个字符与 SuS_u 相同),且 iavi \ge a_v,且 SuS_uSvS_v 的后缀。

      SuS_uSvS_v 的后缀 在 Trie 上怎么体现?
      在正串 Trie 上,SuS_uSvS_v 的后缀 ⇔ uu后缀树 上是 vv 的祖先。
      所以我们需要建立 后缀自动机 (SAM)后缀树 来处理后缀关系。


    后缀自动机解法

    我们考虑将 所有 SuS_u 的反串 插入一个广义 SAM。
    在 SAM 的 parent 树上,如果 uu 对应的节点是 vv 对应的节点的祖先,则 TuT_uTvT_v 的后缀 ⇔ SuS_uSvS_v 的后缀。

    所以扩展点关系就是 parent 树上的祖先-后代关系


    问题转化到 SAM 的 parent 树上

    对每个 uu,在 SAM 上找到对应节点 posupos_u(反串的结束节点)。
    那么 uu 的扩展点集合 = 在 parent 树中 posupos_u 的子树中的所有 vv

    原问题:
    对每个 uu,对 i=0Sui = 0 \dots |S_u|,求 $ \max_{\substack{v \in \text{subtree}(pos_u) \\ i \ge a_v \\ \text{lcp}(S_u, S_v) \ge i}} val_v $ 其中 lcp(Su,Sv)\text{lcp}(S_u, S_v) 是最长公共前缀长度。


    进一步简化

    注意 lcp(Su,Sv)i\text{lcp}(S_u, S_v) \ge i 在 Trie 上(正串)意味着:uuvv 在深度 ii 时有公共祖先。
    uu 的深度 Su|S_u| 固定,iiuu 的前缀长度,所以 vv 必须和 uu 共享前 ii 个字符。

    在正串 Trie 上,从根到 uu 的路径上深度 ii 的节点 pp,我们要找 vvpp 的子树中,且 vv 在 SAM 的 parent 树中在 uu 的子树中,且 iavi \ge a_v


    实现方案

    1. 建立所有 SuS_u正串 Trie,记录每个节点对应的 uu 集合(可能有多个 uu 共享前缀)。

    2. 建立所有 SuS_u 反串的 广义 SAM,记录每个节点对应的 uu 集合(可能有多个 uu 对应同一个节点,如果它们反串后缀相同)。

    3. 在 SAM 的 parent 树上 DFS,得到每个节点的子树中所有 (av,valv)(a_v, val_v) 对。

    4. 对 Trie 上每个节点 pp(深度 dd),它子树中所有 uu 的扩展点 vv 满足 davd \ge a_v 的最大 valvval_v 可以预处理:
      对每个深度 dd,维护一个数据结构,支持:添加 (av,valv)(a_v, val_v),查询所有 avda_v \le d 的最大 valvval_v
      由于 dd 从 0 到 nn,我们可以用线段树按 ava_v 存储最大值,查询前缀最大值。

    5. 对每个 uu,在 Trie 上从根到 uu 路径上每个深度 ii,查询该深度节点对应的最大 valval,然后求和。


    算法步骤

    1. 读入,建树,得到每个 SuS_u
    2. 建正串 Trie,节点记录深度、对应哪些 uu 的路径经过它。
    3. 建反串广义 SAM,记录每个节点对应哪些 uu 的结束位置。
    4. 在 SAM parent 树上 DFS 合并子树信息((av,valv)(a_v, val_v) 集合)。
    5. 在 Trie 上 DFS,进入节点时把该节点在 SAM 中对应集合的 (av,valv)(a_v, val_v) 加入全局线段树(按 ava_v),退出时撤销。
    6. 对每个 Trie 节点 pp(深度 dd),记录 maxval[d]=maxval[d] = 线段树查询 [0,d][0, d] 的最大值。
    7. 对每个 uuansuans_u = 从深度 0 到 Su|S_u|maxvalmaxval 之和。

    复杂度

    • Trie 和 SAM 节点数 O(n)O(n)
    • 线段树更新 O(logn)O(\log n)
    • O(nlogn)O(n \log n)

    • 1

    信息

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