随机化
题目
为了证明
K
n
o
w
N
a
m
e
B
l
o
g
e
r
\sf KnowNameBloger
KnowNameBloger 常数巨大,邪恶的
H
a
n
d
I
n
D
e
v
i
l
\sf HandInDevil
HandInDevil 与炎翼鸟决定在 grader.exe
里面动一些手脚。
题目输入为一棵树。定义「标枪」为,这个点的点权是这个点到根的链上所有节点的权值最大值。形式化的,点 x x x 是「标枪」当且仅当 ∀ y ∈ p a t h ( x , r o o t ) , v y < v x \forall y\in{\rm path}(x,root),\;v_y<v_x ∀y∈path(x,root),vy<vx 。如果有 c c c 个「标枪」点,那么 K n o w N a m e B l o g e r \sf KnowNameBloger KnowNameBloger 的代码运行速度会变成原来的 k c k^c kc 倍( k k k 是 A r e x t r e \sf Arextre Arextre 设定的常数)。
然后 i C u \sf iCu iCu 用随机排列给树分配了点权。我们已经看到 K n o w N a m e B l o g e r \sf KnowNameBloger KnowNameBloger 的代码跑了 1 0 1 0 10 10^{10^{10}} 101010 秒,我们只需要求出,她的代码运行速度的倍数加成(即 k c k^c kc)的期望。由于她的代码常数实在太大,你只需要输出 k c k^c kc 的期望值乘 n ! n! n! 再取模 998244353 998244353 998244353 后的结果。
思路
先考虑一个暴力。称「标枪」为黑点,非「标枪」为白点,先 2 n 2^n 2n 枚举颜色,然后每个点似乎就有 d e p t h depth depth 个点权大小关系限制?
事实上,黑点的白点祖先必然小于它,因为白点 < < < 根 < < < 黑点。还有,一条链上的 k k k 个黑点是一个连不等号的关系,即最深的 > > > 次深的 > > > ⋯ \cdots ⋯ > > > 最浅的(即根节点)。这是黑点的情况,白点也是类似的。所以最终 精简为了只有两种限制:
- 白点的点权 < < < 第一个黑点祖先的点权。
- 黑点的点权 > > > 第一个黑点祖先的点权。
如果点权大的向点权小的连边,这就会形成一个 树形结构,因为每个点只连出一条边(而根节点无出边)。这个东西大家都会,随意选择一个点当作根,然后 容斥向下的边,一部分钦定为向上,容斥系数为 − 1 -1 −1 的这种边的数量次方,剩余的向下边砍掉。向上的边,就是每个点必须是子树内最小值,经典问题了,直接 ∏ 1 s i z e \prod{1\over size} ∏size1 就行。
在本题中,就指定原树的树根为新树的树根。现在就可以设计 d p \tt dp dp 状态了。设 f ( i , j ) f(i,j) f(i,j) 表示,以 i i i 为根的子树中,总共向上连的点有 j j j 个(即,需要获得父节点的所有树的大小之和),方案数(含容斥系数)之和。这里的概率为点权是 1 1 1 到 s i z e i size_i sizei 的排列的情况。考虑转移。
一个巧妙之处是,不同子树的 期望值可以直接相乘。因为 p ( a ) ⋅ k a ⋅ p ( b ) ⋅ k b = p ( a + b ) ⋅ k a + b p(a)\cdot k^a\cdot p(b)\cdot k^b=p(a+b)\cdot k^{a+b} p(a)⋅ka⋅p(b)⋅kb=p(a+b)⋅ka+b 。所以子树内有 j j j 条向上的边的方案数之和 g ( j ) g(j) g(j) 就是子树的 f f f 的卷积。
- 如果是白点:若它是断开了边的那一类,那么上下是独立的,期望的可加性得 f ( i , j ) += g ( j ) f(i,j)\operatorname{+=}g(j) f(i,j)+=g(j) 。若它是改成向上边的一类,由于白点在新树上没有子节点,所以 1 s i z e 1\over size size1 就是 1 1 1,即 f ( i , j + 1 ) − = g ( j ) f(i,j+1){-\text=}g(j) f(i,j+1)−=g(j) 。
- 如果是黑点:所有子树内的黑点都得连向他。别忘了计算概率。即 f ( i , j + 1 ) += k ⋅ g ( j ) j + 1 f(i,j+1)\operatorname{+=}{k\cdot g(j)\over j+1} f(i,j+1)+=j+1k⋅g(j) 。
然后就 O ( n 2 ) \mathcal O(n^2) O(n2) 做完了。
三元组
题目
一棵
n
(
n
⩽
1
0
6
)
n\;(n\leqslant 10^6)
n(n⩽106) 个点的树,记
d
i
s
(
u
,
v
)
dis(u,v)
dis(u,v) 为树上
u
,
v
u,v
u,v 最短距离的长度(边的长度均为
1
1
1),请计算满足下面条件的有序三元组
⟨
A
,
B
,
C
⟩
\langle A,B,C\rangle
⟨A,B,C⟩ 的个数:
∣
{
A
,
B
,
C
}
∣
=
3
,
d
i
s
(
A
,
B
)
≤
max
[
d
i
s
(
A
,
C
)
,
d
i
s
(
B
,
C
)
]
\big|\{A,B,C\}\big|=3,\;dis(A,B)\le\max[dis(A,C),dis(B,C)]
∣
∣{A,B,C}∣
∣=3,dis(A,B)≤max[dis(A,C),dis(B,C)]
思路
看上去很恐怖,但是仔细想一想,这东西是个 轮换式。这说明,对于任意的
A
,
B
,
C
A,B,C
A,B,C,把它们重新排列后就会计数特定次数。比如此处,欲求
c
≤
max
(
b
,
a
)
c\le\max(b,a)
c≤max(b,a) 的数量,不妨设
c
<
b
<
a
c<b<a
c<b<a,那么可行的排列就是
⟨
c
,
b
,
a
⟩
,
⟨
c
,
a
,
b
⟩
,
⟨
b
,
c
,
a
⟩
,
⟨
b
,
a
,
c
⟩
\langle c,b,a\rangle,\langle c,a,b\rangle,\langle b,c,a\rangle,\langle b,a,c\rangle
⟨c,b,a⟩,⟨c,a,b⟩,⟨b,c,a⟩,⟨b,a,c⟩
但是有些特殊情况。如果 c ≤ b = a c\le b=a c≤b=a,那么可行的排列有全部六种。所以,我们只需要考虑这种特殊情况,即 最大值与次大值相等。
这种情况会长什么样子呢?不难发现,一定可以找到一个点 x x x 使得 x x x 到 A , B , C A,B,C A,B,C 三者的路径不相交。(因为 x x x 就是 l c a ( A , B ) , l c a ( B , C ) , l c a ( A , C ) lca(A,B),lca(B,C),lca(A,C) lca(A,B),lca(B,C),lca(A,C) 三者中最深的那个。)如果三条路径长度分别为 a , b , c a,b,c a,b,c,不妨设 a ≤ b ≤ c a\le b\le c a≤b≤c,那么最大值为 b + c b+c b+c,次大值为 a + c a+c a+c,二者要相等,所以 a = b a=b a=b 。
那么考虑 枚举 “中心点”。如果最短的两条都在子树内,就是子树内选等深、子树外选足够长。如果最长的一条在子树内,就是子树内选不等深,子树外选较短深度者。
- 记 f ( x , i ) f(x,i) f(x,i) 为,使得 l c a ( u , v ) = x lca(u,v)=x lca(u,v)=x 且 d i s ( u , x ) > d i s ( v , x ) = i dis(u,x)>dis(v,x)=i dis(u,x)>dis(v,x)=i 的无序二元组 ⟨ u , v ⟩ \langle u,v\rangle ⟨u,v⟩ 的数量。
- 记 g ( x , i ) g(x,i) g(x,i) 为,使得 l c a ( u , v ) = x lca(u,v)=x lca(u,v)=x 且 d i s ( u , x ) = d i s ( v , x ) = i dis(u,x)=dis(v,x)=i dis(u,x)=dis(v,x)=i 的无序二元组 ⟨ u , v ⟩ \langle u,v\rangle ⟨u,v⟩ 的数量。
- 记 h ( x , i ) h(x,i) h(x,i) 为,使得 l c a ( x , u ) ≠ x lca(x,u)\ne x lca(x,u)=x(即 u u u 在子树外)且 d i s ( x , u ) ≤ i dis(x,u)\le i dis(x,u)≤i 的 u u u 的数量。
此时 x x x 对答案的贡献就可以求了。
- 最短的两条在子树内,内部选择 g ( x , i ) g(x,i) g(x,i),外部选择 h ( x , i − 1 ) h(x,i-1) h(x,i−1) 以外的点。
- 最长的一条在子树内,内部选择 f ( x , i ) f(x,i) f(x,i),外部选择 h ( x , i ) − h ( x , i − 1 ) h(x,i)-h(x,i-1) h(x,i)−h(x,i−1) 。
然后问题转化为,怎么求 f , g , h f,g,h f,g,h 三个值。你要先观察到 i i i 的范围:因为 g ( x , i ) g(x,i) g(x,i) 要选两个,所以 i i i 的范围是 短链长度(“短链” 即次长链),毕竟长链上只能选一个。同理可知 f ( x , i ) f(x,i) f(x,i) 中 i i i 的范围是短链长度。
于是乎,我们可以用经典长链剖分求出 p ( x , i ) p(x,i) p(x,i) 为 x x x 的子树内、到 x x x 的距离为 i i i 的点的数量,然后 暴力计算 出 f f f 和 g g g(就是先硬算,然后减去儿子节点以保证 l c a = x lca=x lca=x 成立)。
然而
h
h
h 怎么求呢?先试着写一写递推式吧。
h
(
x
,
i
)
=
h
(
f
a
,
i
−
1
)
+
∑
j
=
0
i
−
1
p
(
f
a
,
j
)
−
∑
j
=
0
i
−
2
p
(
x
,
j
)
h(x,i)=h({\rm fa},i-1)+\sum_{j=0}^{i-1} p({\rm fa},j)-\sum_{j=0}^{i-2}p(x,j)
h(x,i)=h(fa,i−1)+j=0∑i−1p(fa,j)−j=0∑i−2p(x,j)
再想想,我们询问的 h ( x , i ) h(x,i) h(x,i) 中 i i i 不超过短链长度(由 f , g f,g f,g 的 “局限性” 导致),我们不妨慷慨一点,改成 长链长度,那么 h ( f a , i − 1 ) h({\rm fa},i-1) h(fa,i−1) 中的 i − 1 i-1 i−1 的范围是 x x x 的长链长度 − 1 -1 −1 。众所周知 f a {\rm fa} fa 的长链长度至少是 x x x 的长链长度 + 1 +1 +1,所以够用。
再一看,这又是长链剖分经典式子。当 x x x 与 f a \rm fa fa 在同一长链上时,若 i i i 超过 f a \rm fa fa 的短链长度,那后面这两个 ∑ \sum ∑ 的差值就不再变化了,可以打 整体加的懒标记,前缀减去此标记来修正。这个差值最好是先用另一个数组存储(因为它的含义就是 f a \rm fa fa 去掉 x x x 的子树之后的 p p p 值)。
当 x x x 与 f a \rm fa fa 不在同一长链上时,可以 O ( \mathcal O( O( x x x 的长链长度 ) ) ) 暴力计算。当然,由于这里用到了 p p p,所以必须要用 可回退数据结构 维护 p p p,才能在自顶向下的 h h h 计算中得到正确的 p p p 值。这东西听上去恐怖,其实就是 “时光倒流”,把加上去的短链的贡献减掉即可。
那么整道题就做完了。时间复杂度 O ( n ) \mathcal O(n) O(n),但是常数巨大。
长( c h a ˊ n g cháng chaˊng)者
题目
一个长度为 n ( n ⩽ 1 0 5 ) n(n\leqslant 10^5) n(n⩽105) 的排列,有些位置上的数字已经确定了,剩下位置上的数字不确定。你要确定剩下位置上的数字,让得到的排列的最长上升子序列长度尽量长。
思路
回想一般的 L I S \tt LIS LIS 做法。常见的做法是 g ( x ) g(x) g(x) 表示以 x x x 作为结尾的值,最长的 L I S \tt LIS LIS 。其实,本质就是 f ( i ) f(i) f(i) 的转移条件为 p j < p i ∧ j < i p_j<p_i\wedge j<i pj<pi∧j<i,用枚举顺序去掉了第二维,利用单调性将树状数组改成了二分罢了。
在这里我们当然还可以设 f ( i ) f(i) f(i) 为以 i i i 结尾的最长 L I S \tt LIS LIS 。如果 p i p_i pi 是未知的,怎么转移呢?当然是让 p i p_i pi 尽量小啊!如果后面有人又是从 i i i 转移的,也就跟着设置为尽可能小。直到出现已知的 p i p_i pi 。也就是说,中间的转移都只是为了已知的 p i p_i pi 作铺垫。
那我们干脆要求
p
i
p_i
pi 是已知的。枚举上一个确定的位置
j
(
j
<
i
)
j(j<i)
j(j<i) 则有
f
(
i
)
=
max
p
j
<
p
i
{
f
(
j
)
+
min
(
c
i
−
c
j
,
r
i
−
r
j
)
}
+
1
f(i)=\max_{p_j<p_i}\big\{f(j)+\min(c_i-c_j,r_i-r_j)\big\}+1
f(i)=pj<pimax{f(j)+min(ci−cj,ri−rj)}+1
其中 c i c_i ci 为下标 [ 1 , i ] [1,i] [1,i] 中有多少个位置不确定。即 c i − c j c_i-c_j ci−cj 为下标 ( j , i ] (j,i] (j,i] 中空缺的 p p p 。而 r i r_i ri 表示 [ 1 , i ] [1,i] [1,i] 中有多少个 p p p 未使用。即 r i − r j r_i-r_j ri−rj 表示,对于所有 p ∈ ( j , i ] p\in(j,i] p∈(j,i],有多少个 p p p 没出现过。
式子写出来了,发现是 O ( n 2 ) \mathcal O(n^2) O(n2) 的。可笑!优化方法不都写在第一自然段吗?这种问题也能难倒我们?唯一特别的不过是这个 min { c i − c j , r i − r j } \min\{c_i{-}c_j,\;r_i{-}r_j\} min{ci−cj,ri−rj} 罢了。讨论一下 ( c i − r i ) (c_i{-}r_i) (ci−ri) 与 ( c j − r j ) (c_j{-}r_j) (cj−rj) 的值,很容易就能确定选择的是哪一项。
然后问题变成了 三维偏序,即 j < i , p j < p i , c j − r j < c i − r i j<i,\;p_j<p_i,\;c_j-r_j<c_i-r_i j<i,pj<pi,cj−rj<ci−ri 。最外层 c d q \tt cdq cdq 分治,内部 t w o p o i n t e r s \rm two\;pointers twopointers 的时候用 B I T \tt BIT BIT 辅助一下。复杂度 O ( n log 2 n ) \mathcal O(n\log^2n) O(nlog2n) 。
多项式挑战
题目
有一棵无穷大的完全二叉树 T T T,任意一个点都有两个子节点。
给定一棵有限的二叉树 G G G,满足除叶节点外每个节点都有恰好两个儿子,你需要把 G G G 嵌入 T T T 中。具体而言,你需要找一个单射 f : G ↦ T f:G\mapsto T f:G↦T 满足:
- 对于 G G G 中的每个非叶节点 u u u,设其两个子节点分别为 l , r l,r l,r,则 f ( l ) f(l) f(l) 在 f ( u ) f(u) f(u) 的左子树中,且 f ( r ) f(r) f(r) 在 f ( u ) f(u) f(u) 的右子树中。
- 对于 G G G 中的每个叶节点 v v v, f ( v ) f(v) f(v) 的深度必须恰好为 h v h_v hv,其中一个点的深度是它到根节点所需要经过的边数。 h h h 是一个给定的数组。
你需要求方案数对 1 0 9 + 7 10^9+7 109+7 取模的结果。两个方案不同,当且仅当存在一个点 u u u 使得 f ( u ) f(u) f(u) 在两个方案中不同。
数据范围较小, n ≤ 5 × 1 0 3 n\le 5\times 10^3 n≤5×103 且 h i ≤ 1 0 9 h_i\le 10^9 hi≤109 。同时也请注意, f ( 1 ) f(1) f(1) 不一定需要是 T T T 的根节点;可能有无解的情况。
思路
考虑朴素的
d
p
\tt dp
dp,用
g
(
i
,
j
)
g(i,j)
g(i,j) 表示
f
(
i
)
f(i)
f(i) 的深度至少为
j
j
j 时,子树内的答案。那么
g
(
i
,
j
)
=
∑
x
=
j
+
∞
2
x
−
j
⋅
g
(
l
,
x
+
1
)
⋅
g
(
r
,
x
+
1
)
g(i,j)=\sum_{x=j}^{+\infty}2^{x-j}\cdot g(l,x{+}1)\cdot g(r,x{+}1)
g(i,j)=x=j∑+∞2x−j⋅g(l,x+1)⋅g(r,x+1)
如果再加一个后缀和优化,即
g
(
i
,
j
)
=
2
⋅
g
(
i
,
j
+
1
)
+
g
(
l
,
j
+
1
)
⋅
g
(
r
,
j
+
1
)
g(i,j)=2\cdot g(i,j\text+1)+g(l,j\text+1)\cdot g(r,j\text+1)
g(i,j)=2⋅g(i,j+1)+g(l,j+1)⋅g(r,j+1)
就获得了一个 O ( h ⋅ n ) \mathcal O(h\cdot n) O(h⋅n) 的优秀算法。
按照这个方向走,就会 进入死胡同 了。思路明明差不多,但是朝着这个方向推,就会颗粒无收。这究竟是为什么啊?
我们不得不更改定义。设
d
(
i
,
j
)
=
g
(
i
,
j
)
−
2
g
(
i
,
j
+
1
)
d(i,j)=g(i,j)-2g(i,j{+}1)
d(i,j)=g(i,j)−2g(i,j+1),即
f
(
i
)
f(i)
f(i) 深度恰好为
j
j
j 的答案。那么有转移
d
(
i
,
j
)
=
(
∑
x
>
j
d
(
l
,
x
)
2
x
−
j
−
1
)
(
∑
x
>
j
d
(
r
,
x
)
2
x
−
j
−
1
)
d(i,j)= \left(\sum_{x>j}d(l,x)2^{x-j-1}\right) \left(\sum_{x>j}d(r,x)2^{x-j-1}\right)
d(i,j)=(x>j∑d(l,x)2x−j−1)(x>j∑d(r,x)2x−j−1)
为了 尽可能将
x
x
x 与
j
j
j 撇清关系,不再用原有的
g
(
i
,
j
)
=
∑
x
⩾
j
d
(
i
,
x
)
g(i,j)=\sum_{x\geqslant j}d(i,x)
g(i,j)=∑x⩾jd(i,x) 而是
g
(
i
,
j
)
=
∑
x
>
j
2
x
⋅
d
(
i
,
x
)
g(i,j)=\sum_{x>j}2^{x}\cdot d(i,x)
g(i,j)=x>j∑2x⋅d(i,x)
那么
d
(
i
,
j
)
=
2
−
2
j
−
2
⋅
g
(
l
,
j
)
⋅
g
(
r
,
j
)
d(i,j)=2^{-2j-2}\cdot g(l,j)\cdot g(r,j)
d(i,j)=2−2j−2⋅g(l,j)⋅g(r,j)
而后 不难发现 仍然可以用多项式去拟合
g
(
i
,
j
)
g(i,j)
g(i,j) 。不过肯定不是
j
j
j 的幂级数。因为你可以大概写出
g
(
i
,
j
)
=
∑
x
>
j
2
x
⋅
d
(
i
,
x
)
=
∑
x
>
j
2
x
⋅
2
−
2
x
−
2
⋅
g
(
l
,
x
)
⋅
g
(
r
,
x
)
\begin{aligned} g(i,j)&=\sum_{x>j}2^{x}\cdot d(i,x)\\ &=\sum_{x>j}2^{x}\cdot 2^{-2x-2}\cdot g(l,x)\cdot g(r,x) \end{aligned}
g(i,j)=x>j∑2x⋅d(i,x)=x>j∑2x⋅2−2x−2⋅g(l,x)⋅g(r,x)
然后 不难发现 这是 关于
2
−
j
2^{-j}
2−j 的幂级数。形式化地说,存在一个
G
i
(
x
)
=
∑
j
=
0
k
i
a
i
j
x
j
G_i(x)=\sum_{j=0}^{k_i}a_{ij}x^j
Gi(x)=∑j=0kiaijxj 使得
g
(
i
,
j
)
=
G
i
(
2
−
j
)
g(i,j)=G_i(2^{-j})
g(i,j)=Gi(2−j)
这是因为
G
i
(
2
−
j
)
=
∑
x
>
j
2
−
x
−
2
⋅
G
l
(
2
−
x
)
⋅
G
r
(
2
−
x
)
G_i(2^{-j})=\sum_{x>j}2^{-x-2}\cdot G_l(2^{-x})\cdot G_r(2^{-x})
Gi(2−j)=x>j∑2−x−2⋅Gl(2−x)⋅Gr(2−x)
如果记
B
(
x
)
=
G
l
(
x
)
⋅
G
r
(
x
)
=
∑
i
=
0
k
l
+
k
r
b
i
x
i
B(x)=G_l(x)\cdot G_r(x)=\sum_{i=0}^{k_l+k_r}b_ix^i
B(x)=Gl(x)⋅Gr(x)=∑i=0kl+krbixi 则
G
i
(
2
−
j
)
=
∑
x
>
j
2
−
x
−
2
∑
t
=
0
k
l
+
k
r
b
t
(
2
−
x
)
t
=
∑
t
=
0
k
l
+
k
r
b
t
∑
x
>
j
2
−
x
−
2
×
2
−
x
t
=
1
4
∑
t
=
0
k
l
+
k
r
b
t
∑
x
>
j
2
−
x
(
t
+
1
)
=
1
4
∑
t
=
0
k
l
+
k
r
b
t
⋅
2
−
j
(
t
+
1
)
−
2
−
h
(
t
+
1
)
2
t
+
1
−
1
\begin{aligned} G_i(2^{-j})&=\sum_{x>j}2^{-x-2}\sum_{t=0}^{k_l+k_r}b_t(2^{-x})^t\\ &=\sum_{t=0}^{k_l+k_r}b_t\sum_{x>j}2^{-x-2}\times 2^{-xt}\\ &={1\over 4}\sum_{t=0}^{k_l+k_r}b_t\sum_{x>j}2^{-x(t+1)}\\ &={1\over 4}\sum_{t=0}^{k_l+k_r}b_t\cdot {2^{-j(t+1)}-2^{-h(t+1)}\over 2^{t+1}-1} \end{aligned}
Gi(2−j)=x>j∑2−x−2t=0∑kl+krbt(2−x)t=t=0∑kl+krbtx>j∑2−x−2×2−xt=41t=0∑kl+krbtx>j∑2−x(t+1)=41t=0∑kl+krbt⋅2t+1−12−j(t+1)−2−h(t+1)
所以
G
i
(
x
)
=
1
4
∑
t
=
0
k
l
+
k
r
b
t
2
t
+
1
−
1
⋅
(
x
t
+
1
−
2
−
h
(
t
+
1
)
)
G_i(x)={1\over 4}\sum_{t=0}^{k_l+k_r}{b_t\over 2^{t+1}-1} \cdot(x^{t+1}-2^{-h(t+1)})
Gi(x)=41t=0∑kl+kr2t+1−1bt⋅(xt+1−2−h(t+1))
显然仍然是多项式。只剩下一个问题了, k i = k l + k r + 1 k_i=k_l+k_r+1 ki=kl+kr+1 的范围是什么呢?答案是子树内的点数减叶子数。因为对于叶子节点 u u u, g ( u , j ) = 2 h u ( j < h u ) g(u,j)=2^{h_u}\;(j<h_u) g(u,j)=2hu(j<hu) 是零次的。
卷积可以暴力做,因为每一对点在 l c a lca lca 提供 O ( 1 ) \mathcal O(1) O(1) 的复杂度,总复杂度 O ( n 2 ) \mathcal O(n^2) O(n2) 。