LOJ3053 「十二省联考2019」希望

0

部署方案合法的条件是:存在一个点 u u u,使得所有搜救范围都包含 u u u且所有在搜救范围中出现过的点到 u u u的距离不超过 L L L。此时我们称部署方案可以被点 u u u识别。

定义一种部署方案可以被一条边识别,当且仅当这条边的两个端点都能识别它。

显然,对于某种部署方案,可以识别它的 u u u会构成一个连通块,而连通块点数 - 边数 = 1。所以,(每个点可以识别的部署方案数 - 每条边可以识别的部署方案数)就是答案。

s u s_u su表示包含 u u u且所有点到 u u u的距离均不超过 L L L的连通块数,设 s ( x , y ) s_{(x,y)} s(x,y)表示既包含在 s x s_x sx里又包含在 s y s_y sy里的连通块数,则

A n s = ∑ u s u k − ∑ ( x , y ) ∈ T s ( x , y ) k Ans = \sum_u s_u^k - \sum_{(x,y) \in T} s_{(x,y)}^k Ans=usuk(x,y)Ts(x,y)k

1

d p dp dp计算 s u , s ( x , y ) s_u,s_{(x,y)} su,s(x,y)

f u , j f_{u,j} fu,j表示只包含 u u u子树内的点,且所有点到 u u u的距离不超过 j j j,且包含了 u u u的连通块数。设 g u , j g_{u,j} gu,j表示包含了 u u u的父亲 f a u fa_u fau,且不包含 u u u的子树内的点,且所有点到 f a u fa_u fau的距离不超过 j j j的连通块数。距离定义为两个点之间最短路上的边数。

f u , j = ∏ v ∈ s o n u ( f v , j − 1 + 1 ) − 1 g u , j = ( g f a u , j − 1 + 1 ) ∏ v ∈ s o n f a u , v ≠ u ( f v , j − 1 + 1 ) s u = f u , L ⋅ ( g u , L − 1 + 1 ) , s ( u , f a u ) = f u , L − 1 ⋅ g u , L − 1 f_{u,j} = \prod_{v\in son_u} (f_{v,j-1}+1) - 1\\ g_{u,j} = (g_{fa_u,j-1}+1)\prod_{v\in son_{fa_u},v\neq u}(f_{v,j-1}+1)\\ s_u = f_{u,L}\cdot (g_{u,L-1}+1),s_{(u,fa_u)}=f_{u,L-1}\cdot g_{u,L-1} fu,j=vsonu(fv,j1+1)1gu,j=(gfau,j1+1)vsonfau,v=u(fv,j1+1)su=fu,L(gu,L1+1),s(u,fau)=fu,L1gu,L1

2

用长链剖分优化dp。

l e n u len_u lenu表示 u u u的子树中深度最深的点到 u u u的距离。观察可知 f u , l e n u = f u , l e n u + 1 = f u , l e n u + 2 ⋯ f_{u,len_u} = f_{u,len_u+1} = f_{u,len_u+2} \cdots fu,lenu=fu,lenu+1=fu,lenu+2,所以我们只需要算 f u , 0 , f u , 1 , ⋯ f u , l e n u f_{u,0},f_{u,1},\cdots f_{u,len_u} fu,0,fu,1,fu,lenu就可以了。

处理某个点的 f f f的时候,直接让它继承重儿子的信息(这一步要求支持全局+1的操作)。合并轻儿子 v v v的时候,对于 f v , 0 , f v , 1 ⋯ f v , l e n v f_{v,0},f_{v,1}\cdots f_{v,len_v} fv,0,fv,1fv,lenv可以直接暴力,剩下的相当于是令 f u f_u fu数组的一个后缀乘上 f v , l e n v f_{v,len_v} fv,lenv

如果 f v , l e n v f_{v,len_v} fv,lenv不为 0 0 0的话,我们可以让 f u , 0 , f u , 1 ⋯ f u , l e n v f_{u,0},f_{u,1} \cdots f_{u,len_v} fu,0,fu,1fu,lenv都乘上 f v , l e n v f_{v,len_v} fv,lenv的逆元(注意,不应是直接对数组中的数进行乘 f v , l e n v f_{v,len_v} fv,lenv的逆元的操作,而应该将数组中的值赋为“经过当前的全局标记的运算之后为 f u , i f v , l e n v f_{u,i}\over f_{v,len_v} fv,lenvfu,i”的值),然后打上全局乘以 f v , l e n v f_{v,len_v} fv,lenv的标记。

如果 f v , l e n v f_{v,len_v} fv,lenv 0 0 0,就相当于是让一段后缀都变成了 0 0 0,我们可以另外维护一个标记 ( l , x ) (l,x) (l,x),表示从 l l l开始的位置,数组中的值都是 x x x(同理, x x x不一定是 0 0 0,而是“经过当前的全局标记的运算之后为 0 0 0”的值)。

g g g的维护则要更加麻烦一些。首先,我们将所有的链分成两类:长度小于 L − 1 L-1 L1的,我们只需要记录链顶元素 u u u g u , L − 1 − l e n u , g u , L − 1 − l e n u + 1 ⋯ g u , L − 1 g_{u,L-1-len_u},g_{u,L-1-len_u+1} \cdots g_{u,L-1} gu,L1lenu,gu,L1lenu+1gu,L1就能够算出这个子树内所有点的 g v , L − 1 g_{v,L-1} gv,L1;长度大于等于 L − 1 L-1 L1的,记录链顶元素的 u u u g u , 0 , g u , 1 ⋯ g u , L − 1 g_{u,0},g_{u,1} \cdots g_{u,L-1} gu,0,gu,1gu,L1即可。而从某个点到它的重儿子时, g u g_u gu的长度至多加 1 1 1。这样状态数降到了 O ( n ) O(n) O(n)

直接让重儿子继承当前点的 g g g(这个也要求支持全局+1),然后把其他儿子的贡献 ( f v , j + 1 ) (f_{v,j}+1) (fv,j+1)合并上来(这个需要支持对后缀的乘法,与 f f f的处理类似)。而对于轻儿子 v v v,把 ∏ v ′ ∈ s o n u , v ′ ≠ v ( f v ′ , j + 1 ) \prod_{v'\in son_u,v'\neq v}(f_{v',j}+1) vsonu,v=v(fv,j+1)分为三部分:1.在我们处理这个轻儿子之前遍历过的轻儿子的贡献;2.还没有遍历过的轻儿子的贡献;3.重儿子的贡献。按照 l e n len len从小到大的顺序依次处理轻儿子,就能够及其方便地统计在当前的轻儿子之前遍历过的轻儿子的贡献;在计算 f f f的时候,我们按照轻儿子的 l e n len len从大到小的顺序来合并,把 v v v被并入之后的我们对 f f f的那些操作撤销掉,就可以得到 v v v被并入之前的 f f f,也就是2. 3.两部分的贡献。

3

将儿子按照 l e n len len排序,可以先把重儿子找出来,然后对剩下的进行基数排序。这样总复杂度为 O ( n ) O(n) O(n)

实际上我们需要用到的逆元只有每个点的 f u , l e n u f_{u,len_u} fu,lenu,可以在 O ( n ) O(n) O(n)的时间预处理出它们的逆元。

总复杂度 O ( n ) O(n) O(n)

Code

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值