zoukankan      html  css  js  c++  java
  • CodeForces 1111E. Tree

    题目简述:给定$n leq 10^5$个节点的无根树,以及$q leq 10^5$个询问。每个询问给定$k leq 10^5$个不同的节点$a_1, a_2, dots, a_k$,以及参数$1 leq r leq n, 1 leq m leq min{k, 300}$,求将这$k$个节点分成不超过$m$组(本质不同)的方案数,使得

      ·每组节点至少有一个;

      ·以$r$为根时,任意节点的祖先不与该节点同组。

    解:code

    对每组询问,令$h[a_i]$表示$a_1, a_2, dots, a_k$中$a_i$的祖先(不含自身)的个数。按$h[a_i]$从小到大排序$a_i$后,令$F[i][j]$表示前$i$个节点分成$j$组(本质不同)的合法方案数,则

    $$ F[i][j] = (j-h[a_i])F[i-1][j]+F[i-1][j-1], $$

    特别地,$F[0][j] = [j = 0]$。动态规划的复杂度为$O(mk)$。

    现在的问题是,如何求得$h[a_i]$。若令$h_1[a_i]$表示以节点$1$为根时,$a_1, a_2, dots, a_k$中$a_i$的祖先(含自身)的个数,则

    $$ h[a_i] = h_1[a_i]+h_1[r]-2h_1[ ext{LCA}(a_i, r)]+[ ext{LCA}(a_i, r) in {a_1, a_2, dots, a_k}]-1, $$

    其中$ ext{LCA}(u, v)$表示$u$和$v$的最近公共祖先。

    而$h_1[]$易于计算的,我们可以求树以节点$1$为根的DFS序,则$h_1[]$的维护可化为“区间修改”和“单点询问”的线段树问题。

    求LCA的时间复杂度为$O(nlog n)$预处理以及$O(log n)$单次询问。(其实可以将LCA转化为$pm 1$RMQ问题,做到$O(n)$预处理以及$O(1)$单次询问。但这并不是重点。)

    从而总的时间复杂度为$O(nlog n + K (m+log n))$,其中$K$为所有询问的$k$之和。

    解2:

    计算$h[a_i]$可以看做是$a_i$至$r$的树链上的求和,可以用树链剖分在$O(k log^2 n)$的时间复杂度内直接求得,而不需要经过任何问题的转化。

  • 相关阅读:
    求最长不降子序列

    普通背包问题
    求最大子序列
    最大人品
    C# 显示webBrowser页面加载进度
    Provider 错误 '80004005' 未指定的错误 的最终解决方法
    C# 截取webBrowser网页存为图片
    浅谈Python小数据池
    js文件编译成动态链接库(dll)文件
  • 原文地址:https://www.cnblogs.com/TinyWong/p/10369306.html
Copyright © 2011-2022 走看看