文章目录
Day 1
T1
Description
Solution
用美食节把时间分段,每一段内部采用矩阵乘法,倍增预处理+向量乘矩阵即可。
D1T2
Descriptioin
Solution
算法一
考虑 dp \text{dp} dp。
令 f u , i f_{u,i} fu,i 表示,目前考虑了以 u u u 为根的子树,且 u u u 的祖先中(包含 u u u)离 u u u 最近的 1 1 1 边的深度为 i i i;在此前提下, f u , i f_{u,i} fu,i 为子树内的方案数。这里我们定义边 ( x , y ) (x,y) (x,y) 的深度为 max ( d e p x , d e p y ) \max(dep_x,dep_y) max(depx,depy),其中 d e p x dep_x depx 与 d e p y dep_y depy 分别表示节点 x , y x,y x,y 的深度。
考虑转移。
f u , i = [ l i m u ≤ i ≤ d e p u ] ∏ v ∈ s o n { u } ( f v , i + f v , d e p v ) f_{u,i}=[lim_u \le i \le dep_u]\prod_{v \in son \{u\}} (f_{v,i}+f_{v,dep_v}) fu,i=[limu≤i≤depu]v∈son{u}∏(fv,i+fv,depv)
这里 l i m u lim_u limu 表示,对于所有以 u u u 为一端,以 u u u 祖先 v v v 为另一端的路径,它们的 d e p v dep_v depv 的最大值。注意,若 i i i 超出了 [ l i m u , d e p u ] [lim_u,dep_u] [limu,depu] 的范围,那么 f u , i f_{u,i} fu,i 要么无意义,要么不满足给定的限制。
显然,上面的 dp \text{dp} dp 是 O ( n 2 ) O(n^2) O(n2) 的。考虑优化。
算法二
采用线段树合并优化即可。
具体地说,令当前搜索到 u u u,并已经处理完了所有的子状态。我们先将所有不在 [ l i m u , d e p u ] [lim_u,dep_u] [limu,depu] 中的 i i i 全部清 0 0 0,从而得到了整个 f u f_u fu。此时即将回溯,于是我们将 f u f_u fu 中所有有意义且满足要求的位置全部加上 f u , d e p u f_{u,dep_u} fu,depu,并向 u u u 的父节点合并。
时间复杂度 O ( n log n ) O(n \log n) O(nlogn)。
D1T3
Description
给定一个长度为 n n n 的排列 p p p,每次给定 l 1 , r 1 , l 2 , r 2 l_1,r_1,l_2,r_2 l1,r1,l2,r2,求 [ l 1 , r 1 ] [l_1,r_1] [l1,r1] 中存在多少对 ( i , j ) (i,j) (i,j),满足:
①
i
≤
j
i \le j
i≤j
②
p
i
≤
p
j
p_i \le p_j
pi≤pj
③
p
i
∈
[
l
2
,
r
2
]
p_i \in [l_2,r_2]
pi∈[l2,r2],
p
j
∈
[
l
2
,
r
2
]
p_j \in [l_2,r_2]
pj∈[l2,r2]
1 ≤ n , q ≤ 3 × 1 0 5 1 \le n,q \le 3 \times 10^5 1≤n,q≤3×105,时限 4s \texttt{4s} 4s。
Solution
考虑分块,令块长为 ⌊ n ⌋ = B \lfloor \sqrt n \rfloor=B ⌊n⌋=B。
对于形如 l 1 , r 1 , l 2 , r 2 l_1,r_1,l_2,r_2 l1,r1,l2,r2 的询问,将 [ l 1 , r 1 ] [l_1,r_1] [l1,r1] 划分为 [ l 1 , p − 1 ] [l_1,p-1] [l1,p−1], [ p , q ] [p,q] [p,q] 与 [ q + 1 , r 1 ] [q+1,r_1] [q+1,r1] 三个部分,分别表示开头处的零散快,中间的整块与末尾的零散快。
现在,关键在于处理:
-
[
p
,
q
]
[p,q]
[p,q] 对
[
p
,
q
]
[p,q]
[p,q] 的贡献
- 跨块的贡献
- 块内的贡献
- [ l 1 , p − 1 ] [l_1,p-1] [l1,p−1] 对 [ q + 1 , r 1 ] [q+1,r_1] [q+1,r1] 的贡献
- [ l 1 , p − 1 ] [l_1,p-1] [l1,p−1] 对 [ p , q ] [p,q] [p,q] 的贡献
- [ p , q ] [p,q] [p,q] 对 [ q + 1 , r 1 ] [q+1,r_1] [q+1,r1] 的贡献
- [ l 1 , p − 1 ] [l_1,p-1] [l1,p−1] 对 [ l 1 , p − 1 ] [l_1,p-1] [l1,p−1] 的贡献
- [ q + 1 , r 1 ] [q+1,r_1] [q+1,r1] 对 [ q + 1 , r 1 ] [q+1,r_1] [q+1,r1] 的贡献。
Part 1
考虑 [ p , q ] [p,q] [p,q] 对 [ p , q ] [p,q] [p,q] 的贡献中跨块的贡献。
令
f
i
,
j
f_{i,j}
fi,j 表示第
i
i
i 个块中
j
j
j 出现的次数。
令
g
i
,
j
g_{i,j}
gi,j 表示前
i
i
i 个块中
j
j
j 出现的次数。
不难得到贡献是
∑ x = c d ∑ i = l r f x , i × ( ( g d , r − g d , i ) − ( g x , r − g x , i ) ) \sum_{x=c}^{d} \sum_{i=l}^r f_{x,i} \times ((g_{d,r}-g_{d,i})-(g_{x,r}-g_{x,i})) x=c∑di=l∑rfx,i×((gd,r−gd,i)−(gx,r−gx,i))
c , d c,d c,d 表示 p p p 与 q q q 所在块的编号。
展开成四个部分:
Part 1.1
∑ x = c d ∑ i = l r f x , i × g d , r \sum_{x=c}^d \sum_{i=l}^r f_{x,i} \times g_{d,r} x=c∑di=l∑rfx,i×gd,r
显然,随着 x , i x,i x,i 的变化 g d , r g_{d,r} gd,r 不变,于是可以将 g d , r g_{d,r} gd,r 提出来。
我们预处理出所有 f x f_x fx 的前缀和;查询的时候,枚举 x x x, O ( 1 ) O(1) O(1) 求出 ∑ x = c d f x , i \sum_{x=c}^d f_{x,i} ∑x=cdfx,i 并累加。
Part 1.2
− ∑ x = c d ∑ i = l r f x , i × g d , i -\sum_{x=c}^d \sum_{i=l}^r f_{x,i} \times g_{d,i} −x=c∑di=l∑rfx,i×gd,i
交换一下 ∑ \sum ∑
− ∑ i = l r g d , i ∑ x = c d f x , i -\sum_{i=l}^r g_{d,i} \sum_{x=c}^d f_{x,i} −i=l∑rgd,ix=c∑dfx,i
对于每一个 i i i,预处理出 f x , i f_{x,i} fx,i 的前缀和,查询的时候枚举 i i i, O ( 1 ) O(1) O(1) 求出里面的 ∑ \sum ∑,乘上 g d , i g_{d,i} gd,i 并累加即可。
Part 1.3
− ∑ x = c d ∑ i = l r f x , i × g x , r -\sum_{x=c}^d \sum_{i=l}^r f_{x,i} \times g_{x,r} −x=c∑di=l∑rfx,i×gx,r
与 Part 1.2 \text{Part 1.2} Part 1.2 同理,只不过这里需对每个 x x x 处理出 f x , i f_{x,i} fx,i 前缀和。
Part 1.4
∑ x = c d ∑ i = l r f x , i × g x , i \sum_{x=c}^d \sum_{i=l}^r f_{x,i} \times g_{x,i} x=c∑di=l∑rfx,i×gx,i
维护 p x , i = f x , i × g x , i p_{x,i}=f_{x,i} \times g_{x,i} px,i=fx,i×gx,i 的前缀和即可。
从而,Part 1 单次在 O ( n ) O(\sqrt n) O(n)。
Part 2
考虑 [ p , q ] [p,q] [p,q] 对 [ p , q ] [p,q] [p,q] 的贡献中块内部产生的贡献。显然,这一部分中块与块是独立的,这启发我们去预处理出一些东西。
我们可以对于每一个块,将其内部的 a a a 离散化并记录两个数组 l i s 1 , l i s 2 lis1,lis2 lis1,lis2。对于一个真实值 i i i,该块内不超过它的最大数即为 l i s 1 i lis1_i lis1i,该块内不小于它的最小数即为 l i s 2 i lis2_i lis2i。
离散化后,我们预处理出每一对正序对,并将它们存储在一个 B × B B \times B B×B 的二维表里面,并将这个表做二维前缀和。每次查询的时候,我们枚举一个块,并令 l ′ = l i s 1 l 2 l'=lis1_{l2} l′=lis1l2, r ′ = l i s r 2 r'=lis_{r2} r′=lisr2,查询二维矩阵 [ l ′ , r ′ ] [ l ′ , r ′ ] [l',r'][l',r'] [l′,r′][l′,r′] 的和即可。
从而,Part 2 单次 O ( n ) O(\sqrt n) O(n)。
Part 3
我们在 [ l 1 , p − 1 ] [l_1,p-1] [l1,p−1] 中枚举一个 a i ( a i ∈ [ l 2 , r 2 ] ) a_i(a_i \in [l_2,r_2]) ai(ai∈[l2,r2]),然后在 [ q + 1 , r 1 ] [q+1,r_1] [q+1,r1] 所在块中查表得到 l ′ = l i s 1 a i + 1 , r ′ = l i s 2 r 2 l'=lis1_{a_i+1},r'=lis2_{r_2} l′=lis1ai+1,r′=lis2r2。
现在,我们需要求出, [ q + 1 , r 1 ] [q+1,r_1] [q+1,r1] 中存在多少个在 [ l ′ , r ′ ] [l',r'] [l′,r′] 中的数(注意,已经离散化)。我们对于每个块,对于每个 i i i,预处理一个长度为 B B B 的数组 l i s 3 \color {gold} {lis_3} lis3 表示 i i i 在该块各个位置的出现情况 0 / 1 0/1 0/1,并将其做前缀和,从而每次可以 O ( 1 ) O(1) O(1) 查询。
从而,Part 3 单次 O ( n ) O(\sqrt n) O(n)。
Part 4
枚举一个 [ l 1 + 1 , p − 1 ] [l_1+1,p-1] [l1+1,p−1] 中的数 a i ( a i ∈ [ l 2 , r 2 ] ) a_i(a_i \in [l_2,r_2]) ai(ai∈[l2,r2]),然后调用 g g g 的前缀和数组即可。
从而,Part 4 单次 O ( n ) O(\sqrt n) O(n)。
Part 5
与 Part 4 同理,单次 O ( n ) O(\sqrt n) O(n)。
Part 6
枚举一个 [ l 1 + 1 , p − 1 ] [l_1+1,p-1] [l1+1,p−1] 中的位置 i i i,然后在 l i s 3 \color {gold} {lis_3} lis3 的前缀和数组里面做查询即可。
单次 O ( n ) O(\sqrt n) O(n)。
Part 7
与 Part 6 同理。
综上所述,总时间复杂度 O ( ( n + q ) n ) O((n+q) \sqrt n) O((n+q)n)。
Day 2
T1
Description
Solution
首先,我们对于每一个满足 d i ≥ k d_i \ge k di≥k 的 i i i,均将 i i i 作为某一道菜的唯一原材料。
此时, ∀ i ∈ [ 1 , n ] , d i < k \forall i \in [1,n],d_i<k ∀i∈[1,n],di<k, n − 2 ≤ m ≤ n − 1 n-2 \le m \le n-1 n−2≤m≤n−1 且剩下未做的菜必定由两个不同的原材料制成。
算法一
考虑 m = n − 1 m=n-1 m=n−1 的情况。
首先,一个观察是: 我们不可能同时将菜 ( A , B ) ( B , C ) ( A , C ) (A,B)(B,C)(A,C) (A,B)(B,C)(A,C) 配对,因为我们可以将它换为 ( A , B ) ( A , C ) (A,B)(A,C) (A,B)(A,C) 或 ( A , B ) ( B , C ) (A,B)(B,C) (A,B)(B,C) 或 ( B , C ) ( A , C ) (B,C)(A,C) (B,C)(A,C),这样不仅依然满足要求,还减少了配对的对数。更进一步的,配对方案不存在环。
考虑贪心。我们每次找到最大值 x x x 与另外的任意值 y y y,将它们俩合并得到一道菜,并将 x + y − k x+y-k x+y−k 重新压入。
可以证明,本贪心正确。
算法二
根据算法一,我们可以得到:当 m = n − 1 m=n-1 m=n−1 时, ∑ i = 1 n d i = ( n − 1 ) k \sum_{i=1}^n d_i=(n-1)k ∑i=1ndi=(n−1)k 是存在合法解的充分必要条件。
考虑 m = n − 2 m=n-2 m=n−2 的情况。根据“不存在环”的性质,最终的配对方案一定是一片包含两棵树的森林;从而,我们只需要钦定一组拆分方案,将 d d d 拆分为 d ′ d' d′ 与 d ′ ′ d'' d′′,使得所有 d i ′ d'_i di′ 的和恰好为 k × ( ∣ d ′ ∣ − 1 ) k \times (|d'|-1) k×(∣d′∣−1)。这里 ∣ d ′ ∣ |d'| ∣d′∣ 表示 d ′ d' d′ 的长度。
于是,我们可以将所有的 d i d_i di 都减去 x x x,现在关键在于找到它的一个和为 − k -k −k 的子集。
采用背包即可。时间复杂度 O ( n 2 k ) O(n^2 k) O(n2k)。
算法三
采用 bitset \text{bitset} bitset 来优化这个背包即可通过,总复杂度 O ( n 2 k w ) O(\frac {n^2k}{w}) O(wn2k)。
T2
Description
Solution
Part 1: 性质观察
Lemma 1
令最大的树高为 m a x h maxh maxh,若所有高度不小于 m a x h maxh maxh 的树都能被拼成,那么该森林就是几乎完备的。
Lemma 2
令所有高度为 h h h 的树的集合为 S h S_h Sh。若 T r e e 1 , T r e e 2 ∈ S h Tree_1,Tree_2 \in S_h Tree1,Tree2∈Sh 且 T r e e 1 Tree_1 Tree1 可以生长得到 T r e e 2 Tree_2 Tree2,那么对于给定的森林,只需要判定它是否能够生长成为 T r e e 1 Tree_1 Tree1 即可。
Lemma 3
根据 Lemma 2,我们可以将 S h S_h Sh 中所有可以通过别的树生长得到的树去掉,得到 S S S 的基 S ′ S' S′。
S ′ S' S′ 中仅包含链树。
Lemma 4
若树
T
T
T 不是链树,则它永远不可能通过生长成为链树。
若树
T
T
T 是链树,那么它可以通过生长得到链树。
根据上述四个引理,我们只需要将链树保留,并判断这些链树能否生成所有的高度不小于 m a x h maxh maxh 的链树即可。
Part 2: 链树编码
我们尝试给链树一个递归式的形式化的定义。
若一棵树的节点个数为
1
1
1,那么它就是一棵链树。
若
T
T
T 是一棵链树且其高度超过
1
1
1,当且仅当:
-
令 T T T 的两个儿子的子树分别为 S 1 , S 2 S_1,S_2 S1,S2;特别的,若只有一个儿子,那么该集合为空。
- ① S 1 S_1 S1 为空, S 2 S_2 S2 为链树
- ② S 2 S_2 S2 为空, S 1 S_1 S1 为链树
- ③ ∣ S 1 ∣ = 1 |S_1|=1 ∣S1∣=1, S 2 S_2 S2 为链树
- ④ ∣ S 2 ∣ = 1 |S_2|=1 ∣S2∣=1, S 1 S_1 S1 为链树
我们可以将 T T T 看做当前的子树,将 S 1 , S 2 S_1,S_2 S1,S2 看做两个子问题;这启发我们采用分治来解决本题。
我们可以给链树上的每个节点一个在 [ 1 , 4 ] [1,4] [1,4] 中的编码,表示它的两个子树的状态。我们可以将给定的链树合并到一起,得到一颗四叉树,每条边表示一种状态;并于合并完成后,在四叉树上进行分治处理。
Part 3: 经典分治
若以 u u u 为根的子树合法,当且仅当什么呢?
首先,如果 u u u 是某棵树的叶节点,则合法。
若 u u u 不是叶节点呢?我们考虑分治。具体地说,我们对于 u u u 的四个儿子 v 1 , v 2 , v 3 , v 4 v_1,v_2,v_3,v_4 v1,v2,v3,v4 分别进行分治,判断它们是否合法;若它们全部合法,则子树合法;若不合法,则子树不合法。
注意到,四叉树上节点的数量与输入量同级,且分治的复杂度与四叉树上节点的数量同级,于是本题的复杂度是线性的。
D2T3
咕咕咕