NOI 2020 解题报告

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=[limuidepu]vson{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 ij
p i ≤ p j p_i \le p_j pipj
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 1n,q3×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,p1] [ 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,p1] [ q + 1 , r 1 ] [q+1,r_1] [q+1,r1] 的贡献
  • [ l 1 , p − 1 ] [l_1,p-1] [l1,p1] [ 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,p1] [ l 1 , p − 1 ] [l_1,p-1] [l1,p1] 的贡献
  • [ 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=cdi=lrfx,i×((gd,rgd,i)(gx,rgx,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=cdi=lrfx,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=cdi=lrfx,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=lrgd,ix=cdfx,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=cdi=lrfx,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=cdi=lrfx,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,p1] 中枚举一个 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,p1] 中的数 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,p1] 中的位置 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 dik 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 n2mn1剩下未做的菜必定由两个不同的原材料制成

算法一

考虑 m = n − 1 m=n-1 m=n1 的情况。

首先,一个观察是: 我们不可能同时将菜 ( 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+yk 重新压入。

可以证明,本贪心正确。

算法二

根据算法一,我们可以得到:当 m = n − 1 m=n-1 m=n1 时, ∑ i = 1 n d i = ( n − 1 ) k \sum_{i=1}^n d_i=(n-1)k i=1ndi=(n1)k 是存在合法解的充分必要条件。

考虑 m = n − 2 m=n-2 m=n2 的情况。根据“不存在环”的性质,最终的配对方案一定是一片包含两棵树的森林;从而,我们只需要钦定一组拆分方案,将 d d d 拆分为 d ′ d' d d ′ ′ d'' d,使得所有 d i ′ d'_i di 的和恰好为 k × ( ∣ d ′ ∣ − 1 ) k \times (|d'|-1) k×(d1)。这里 ∣ 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,Tree2Sh 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

咕咕咕

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值