1 条题解

  • 0
    @ 2025-10-25 19:48:49

    「ZJOI2020」传统艺能 题解

    题目分析

    给定一棵广义线段树,执行 kk 次操作,每次操作等概率随机选择一个区间 [l,r][l, r] 进行懒标记操作。求 kk 次操作后,有标记的节点的期望数量。

    核心算法:概率期望 + 矩阵快速幂

    关键思路

    对于每个节点,考虑其在 kk 次操作后被标记的概率,然后利用期望的线性性求和。

    节点状态分类

    对于任意非根节点 xx,定义三种状态:

    • 状态 0:节点 xx 和其父亲都没有标记
    • 状态 1:父亲有标记,但 xx 没有
    • 状态 2:节点 xx 有标记

    概率转移矩阵

    对于每个节点,构建 3×33 \times 3 的转移矩阵 MM,其中 Mi,jM_{i,j} 表示从状态 ii 转移到状态 jj 的概率。

    关键概率计算

    • Include(x)Include(x):操作区间完全包含节点 xx 的概率

      $$Include(x) = \frac{l_x \times (n - r_x + 1)}{\frac{n(n+1)}{2}} $$
    • Intersect(x)Intersect(x):操作区间与节点 xx 相交的概率

      $$Intersect(x) = 1 - \frac{\binom{l_x-1}{2} + \binom{n-r_x}{2}}{\binom{n}{2}} $$
    • Visit(x)Visit(x):操作区间访问到节点 xx 但不访问其父亲的概率

      Visit(x)=Include(x)Include(fax)Visit(x) = Include(x) - Include(fa_x)
    • VisitCousin(x)VisitCousin(x):操作区间访问到父亲但不访问 xx 的概率

      VisitCousin(x)=Intersect(fax)Intersect(x)VisitCousin(x) = Intersect(fa_x) - Intersect(x)

    矩阵构建

    转移矩阵为:

    $$M = \begin{bmatrix} p_{00} & p_{01} & p_{02} \\ 0 & p_{11} & p_{12} \\ 0 & 0 & 1 \end{bmatrix} $$

    其中:

    • $p_{00} = (Include(fa_x) + NoIntersect(fa_x)) \times qV$
    • p01=VisitCousin(x)×qVp_{01} = VisitCousin(x) \times qV
    • p02=Visit(x)×qVp_{02} = Visit(x) \times qV
    • $p_{11} = (NoIntersect(fa_x) + VisitCousin(x)) \times qV$
    • p12=(Include(fax)+Visit(x))×qVp_{12} = (Include(fa_x) + Visit(x)) \times qV

    算法流程

    1. 建树:根据先序遍历的划分位置构建广义线段树
    2. DFS 遍历:对每个节点计算转移矩阵
    3. 矩阵快速幂:计算 MkM^k 得到 kk 次操作后的状态概率
    4. 累加期望:每个节点的状态 2 的概率贡献到答案

    复杂度分析

    • 时间复杂度O(nlogk)O(n \log k),每个节点需要 O(logk)O(\log k) 的矩阵快速幂
    • 空间复杂度O(n)O(n),存储线段树结构

    算法标签

    主要分类

    • 动态规划 ⭐⭐⭐⭐
    • 概率期望 ⭐⭐⭐⭐⭐
    • 矩阵快速幂 ⭐⭐⭐⭐

    技术子标签

    • 状态机设计 ⭐⭐⭐⭐
    • 组合计数 ⭐⭐⭐⭐
    • 线段树性质分析 ⭐⭐⭐⭐

    数学工具

    • 线性代数 ⭐⭐⭐
    • 模运算 ⭐⭐⭐

    代码核心解析

    // 构建转移矩阵
    mat.a[0][0] = (Include(t[x].fa) + NoIntersect(t[x].fa)) % P * qV % P;
    mat.a[0][1] = VisitCousin(x) * qV % P;
    mat.a[0][2] = Visit(x) * qV % P;
    mat.a[1][1] = (NoIntersect(t[x].fa) + VisitCousin(x)) % P * qV % P;
    mat.a[1][2] = (Include(t[x].fa) + Visit(x)) * qV % P;
    mat.a[2][2] = 1;
    
    // 矩阵快速幂计算k次操作后的状态
    ans += qpow(mat, k).a[0][2];
    

    创新点总结

    1. 状态机建模:将复杂的标记传播过程抽象为三状态马尔可夫链
    2. 概率计算:利用组合数学精确计算各种区间操作的概率
    3. 矩阵优化:使用矩阵快速幂处理大规模操作次数 k109k \leq 10^9
    4. 期望线性性:将整体期望分解为每个节点的期望之和

    该解法通过巧妙的概率建模和矩阵优化,成功解决了大规模操作下的期望计算问题。

    • 1

    信息

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