NOI 2021 游记&题解&总结

Travel Notes

Day 0

一天都挺颓的,尤其是晚上打了好几局 Dream League Soccer。

不过这天也成功卡过去了上一场 Div.1+Div.2 的根号分治+整除分块+分块(根号平衡)做法。

晚上出了一道水题,就睡觉了。

Day 1

奇葩,CCF 等到 10 10 10 点才发题,我还以为取消了。

发现 A 似乎并不困难,很快就想到了正解,但是非常难写。于是我看了看后面的 B,C,感觉都可以拿分,于是我就决定了——把 A 的 55 55 55 分暴力写完走人。然后写了一个半小时之后调试完毕,然后测了下大样例,其中一个顺利通过,另一个 RE。调了半天认为是爆栈(实际上是真的 RE 了),然后就抛掉不管了。

接下来我开了 C。观察了半天那个 x → z , y → z x \to z,y \to z xz,yz x → y / y → z x \to y/y \to z xy/yz 的性质并没有发现什么,反倒是发现了这个性质在 m = n − 1 m=n-1 m=n1 时对应一棵外向树。于是我就分类讨论了 k = 0 / 1 k=0/1 k=0/1 的情况,并通过大样例使自己的情况完备了。同时也写了个暴力,期望有 44 44 44 分。

B 首先得到了 k = 2 , n 1 = 10 k=2,n_1=10 k=2,n1=10 的分。然后想了一会儿,发现可以用匈牙利算法二分图匹配来做掉总数不超过 1 1 1 的情况。然后就码了一发,期望有 40 40 40 分。

然后比赛就结束了。最后也没什么好干的,感觉已经做到最好了。

口胡总分: 55 + 40 + 44 = 139 55+40+44=139 55+40+44=139
期望总分: 55 + 40 + 44 = 139 55+40+44=139 55+40+44=139
最终得分 10 \huge{10} 10 + 40 + 44 = 94 +40+44=\huge {94} +40+44=94

Day 3

CCF 故技重施,8:30->9:00,原因是网站炸了。然而我在 8:56 就在网站上看到了题目的名字。

开场看题,感觉题目很难。

先做了 T2。由于我之前做过一道 LOJ NOI Round 的相似的题,所以我很快就得到了 50 50 50 分的做法。然后观察了半天不会正解,于是就写了这 50 50 50 分。共写了三个 Subtask,调了两个小时一刻钟才过了几个大样例。

然后开了 T3。看了样例解释,发现可以容斥。扩展到一般情况,我很快得到了 O ( 2 n n 2 m ) O(2^n n^2m) O(2nn2m) 的做法,很快又得到了 O ( n 2 m + 2 n n ) O(n^2m+2^n n) O(n2m+2nn) 的做法,可以得到 28 28 28 分。然而调了 2 2 2 个多小时硬是没调出来,也因此连 T1 的暴力都没写。

最后三分钟,我决定放弃了。T1 总是输出 0 0 0,T3 就把自己的过不了大样例的代码交上去。

口胡得分: 28 + 50 + 28 = 106 28+50+28=106 28+50+28=106
期望得分: 0 + 50 + 0 = 50 0+50+0=50 0+50+0=50
最终得分: 12 + 0 / 50 + 12 = 24 / 74 \huge{12}+0/50+\huge{12}=\huge{24/74} 12+0/50+12=24/74

T2 把 void 写成了 int,没有返回值,希望 CCF 留命。

Day 3.5

铜牌线 214 214 214 分,发现不管怎么样自己都有了。银牌 310 310 310 分,要是两天都不犯傻逼错误我不就 Ag 了呀啊啊啊……

最近一直在口胡,所以要好好锻炼一下码力了。

Day 10

出分了,果然 168 168 168,被 PMOI 队友 ljs 和巨佬 yzh 吊打。

菜啊……菜啊……菜啊……真的滚 Cu 了

Solutions

D1T1

为方便理解,下面用重边表示将树进行重链剖分后每个节点连向重儿子的边实边表示题目中所谓的重边。

若对样例进行手玩,可以发现——若两个节点 u , v u,v u,v 之间的边是实边,当且仅当 u , v u,v u,v 均被至少一次路径修改覆盖到,且它们上一次被覆盖到的时刻相同。

这启发我们维护一个时间戳来表示每个节点被覆盖的时刻。具体来说,我们先令所有节点权值为 0 0 0,并在第 i i i 次路径修改中将 ( u , v ) (u,v) (u,v) 之间的所有点的权值均改为 i i i。这样一来,问题等价于: 路径摊,查询路径上相邻的权值相等的点对数量。

考虑使用树链剖分+线段树维护。

对于线段树上表示区间 [ l , r ] [l,r] [l,r] 的节点,维护 l l l 的权值 x x x r r r 的权值 y y y,以及区间内相邻等权值点对数 c c c。每次 pushup \text{pushup} pushup 的时候,先令 c c c 为左右儿子的 c c c 之和,再比对左儿子的 y y y 以及右儿子的 x x x,若相同且均不为 1 1 1 则将当前的 c c c 再加上 1 1 1

对于区间修改,采用形如区间摊为某个数 v v v 的懒标记维护。下传的时候,令两个儿子的 x , y x,y x,y 均为 v v v c c c 均为区间长度减 1 1 1 即可。

对于链上修改以及链上查询,套重链剖分的板子即可。注意,也需要考虑两条重链的交界处的贡献,所有还需要进行两次单点查询并进行比对。

时间复杂度 O ( n log ⁡ 2 n ) O(n \log^2 n) O(nlog2n),本题被解决。

D1T2

算法一

首先考虑 k = 2 k=2 k=2 的情况。

M i , j M_{i,j} Mi,j 表示第一层的 i i i 是否有边连向第二层的 j j j。则答案即为

∑ p ( − 1 ) σ ′ ( p ) ∏ i = 1 n M i , p i \sum_{p} (-1)^{\sigma'(p)}\prod_{i=1}^n M_{i,p_i} p(1)σ(p)i=1nMi,pi

其中 p p p 表示一个长度为 n n n 的排列, σ ′ ( p ) \sigma'(p) σ(p) 表示 p p p 的逆序对数。

发现这与行列式的形式一样。因此,答案即为 M M M 的行列式。

算法二

Lemma

只要固定了从第一层的 1 , 2 , 3 , ⋯   , n 1 1,2,3,\cdots,n_1 1,2,3,,n1 开始的路径的结束点,就固定了交点的奇偶性。更为具体的,若将这些结束点排成一个序列 p p p,那么交点数与 σ ′ ( p ) \sigma'(p) σ(p) 同奇同偶。


定义矩阵 M M M,其中 M i , j M_{i,j} Mi,j 表示从第一行的 i i i 走到最后一行的 j j j 的方案数,那么答案就是这个矩阵的行列式。

我们可以通过 dp \text{dp} dp 求出 M M M 中的每个位置的值。具体的,令 f i , j f_{i,j} fi,j 表示从第一行的 i i i 走到当前行 j j j 的方案数,每次枚举 j j j 往下一层的出边 j → k j \to k jk 并将其转移到 f i , k f_{i,k} fi,k。显然,单次转移是 O ( n 1 ) O(n_1) O(n1) 的,总共有 O ( n 1 3 ) O(n_1^3) O(n13) 个状态(注意,上面省略了当前行的编号),所以 dp \text{dp} dp O ( n 1 4 ) O(n_1^4) O(n14) 的。

时间复杂度 O ( ∑ n 1 4 ) O(\sum n_1^4) O(n14),本题被解决。

D1T3

算法一

不难发现,一个节点可以被经过,当且仅当 s s s 可以到达它并且它可以到达 t t t

对于每次查询,从 s s s 往外 dfs \text{dfs} dfs,并在反图上从 t t t 往外 dfs \text{dfs} dfs 即可。

时间复杂度 O ( t ( n + m ) ) O(t(n+m)) O(t(n+m)),竟然可以通过,而且跑得飞快。

算法二

由于 m = n − 1 m=n-1 m=n1 且将该有向图转化为无向图后连通,又因为存在限制( x → z , y → z x \to z,y \to z xz,yz x → y x \to y xy y → x y \to x yx),所以这是一棵外向树

对于每一次询问,我们都读入了 2 k + 2 2k+2 2k+2 个节点。我们以这些节点建立虚树,那么一个可以被经过的点一定在虚树的某条边上或是某个点,且一条边上的各个点等价(即要么全部可以被经过,要么全部不能被经过)。

由于 2 k + 2 2k+2 2k+2 最大只有 6 6 6,因此虚树上最多只有 12 12 12 个点和 11 11 11 条边,我们直接采用算法一暴力计算即可。

时间复杂度 O ( n log ⁡ n + q log ⁡ n ) O(n \log n+q \log n) O(nlogn+qlogn),本题被解决。瓶颈在于虚树中的建立。

算法三

考虑某两条边 u → x , v → x u \to x,v \to x ux,vx。根据题意,必然有 u → v u \to v uv v → u v \to u vu。不妨设 u → v u \to v uv。由于我们只关注图的连通性,而 u u u 到达 x x x 有两种方式 u → x u \to x ux 以及 u → v → x u \to v \to x uvx,所以我们可以直接将边 u → x u \to x ux 去掉。更进一步的,我们对图进行拓扑排序,我们可以只保留所有连向它的拓扑序最大的点

这样一来,每个点的入度至多只有 1 1 1,且至少有一个点(拓扑起点)没有入度。同时,题目中保证,将有向边看成无向边后连通,所以我们得到了一棵外向树

套用算法二的做法即可。时间复杂度依然是 O ( ( n + q ) log ⁡ n ) O((n+q) \log n) O((n+q)logn)

D2T1

首先,将字典中的每个 256 256 256 位二进制数拆成 16 16 16 16 16 16 位二进制数。查询的数做同样处理。

不难发现,因为 k ≤ 15 k \le 15 k15,所以询问数的 16 16 16 个二进制数中至少有一个完全相同。考虑枚举这一位,并在对应的桶中直接枚举满足条件的数。因为字典是纯随机构造的,所以当相同的二进制数定下来后,期望只有 n 2 16 ≈ 7 \frac {n} {2^{16}} ≈ 7 216n7 个数满足条件,因此期望枚举 7 × 16 = 112 7 \times 16=112 7×16=112 个数。若可以 O ( 1 ) O(1) O(1) 进行比对,则复杂度 O ( 112 q ) O(112q) O(112q)

直接暴力比对会将复杂度再乘上 256 256 256,显然无法通过,需要进行优化。

令当前枚举的这个数的 16 16 16 位分别为 x 1 , x 2 , ⋯   , x 16 x_1,x_2,\cdots,x_{16} x1,x2,,x16,询问数的 16 16 16 位分别为 y 1 , y 2 , ⋯   , y 16 y_1,y_2,\cdots,y_{16} y1,y2,,y16,那么我们需要求出 ( x 1 , y 1 ) ( x 2 , y 2 ) , ⋯   , ( x 16 , y 16 ) (x_1,y_1)(x_2,y_2),\cdots,(x_{16},y_{16}) (x1,y1)(x2,y2),,(x16,y16) 这些数对分别有多少位不同。不难想到, ( x , y ) (x,y) (x,y) 的不同位数即为 popcount ( x ⊕ y ) \text{popcount}(x \oplus y) popcount(xy),其中 ⊕ \oplus 表示异或。注意到 x ⊕ y ≤ 2 16 x \oplus y \le 2^{16} xy216,我们可以预处理出所有在 [ 0 , 2 16 ) [0,2^{16}) [0,216) 中的数的在二进制下 1 1 1 的位数,每次 O ( 1 ) O(1) O(1) 调用即可。

期望复杂度 O ( 7 × 16 × 16 × q ) = O ( 1792 q ) O(7 \times 16 \times 16 \times q)=O(1792q) O(7×16×16×q)=O(1792q),卡线通过。

D2T2

D2T3

咕咕咕

Summary

这一场 NOI 发挥出了自己最真实的水平: 会偶尔挂分,会调试不出代码,一道题也做不出来;会灵光乍现部分分,会拼分 ⋯ ⋯ \cdots \cdots

然后总结一下今年考了哪些题目以及自己为啥一题也没做出来。

D1T1 考察了树链剖分以及线段树,作为一道签到题,我没有想到最好写的正解,导致当时选择了放弃。

D1T2 是一个裸的 LGV 板子,我没有学过,理应做不出来。

D1T3 是一个性质题,关键在于将图缩成一棵树,然后建立虚树等操作都是考场上想到的。不过我并没有想到这一点,并没有仔细思考 x → z , y → z x \to z,y \to z xz,yz x → y x \to y xy y → x y \to x yx 的意义,与正解失之交臂。

D2T1 作为一道随机的题目,思维难度较低,想到拆分成 16 16 16 个二进制数并开桶枚举就做完了。然而我被题面惊吓到了,甚至连 bitset \text{bitset} bitset 的暴力都没有调试出来,令人唏嘘。

D2T2 与 LOJ NOI Round #2 D1T1 的第一步相同,我在考场上也成功想到了;然而 W 以及 E 可以被表示为多个矩阵的乘积,同时平衡树维护也是我考场上想不到也做不出来的。

D2T3 难度极大,考察了容斥、dp 以及各种神奇的优化。考场上想到了 28 28 28 分做法,但是并没有调试出来。

编号 数据结构 dp \text{dp} dp 图论 构造 贪心 数学
NOI 2021 D1T1
NOI 2021 D1T2
NOI 2021 D1T3
NOI 2021 D2T1
NOI 2021 D2T2
联合省选 D1T1
联合省选 D1T2
联合省选 D1T3
联合省选 D2T1
联合省选 D2T2
联合省选 D2T3
NOI 2020 D1T1
NOI 2020 D1T2
NOI 2020 D1T3
NOI 2020 D2T1
NOI 2020 D2T2

在国内比赛中, 最终要的毫无疑问是码力。然后是数据结构与图论,其次是性质分析能力以及 dp \text{dp} dp。再其次,是构造,数学与贪心;最后是各种神奇的科技(例如 LGV 引理,扩展 KMP 等)。

在本场比赛中,我最终因为挂分原因与 Ag 失之交臂;换言之,如果训练好了码力,我就能擦线 Ag。关于 A 以及 E,我均因为对代码能力不够的畏惧不敢写数据结构题,因此失去了大量的分,所以码力真的起到了非常非常重要的作用。其他的东西可能都是平时的积累,码力虽然也是平时的积累,可是它是 OI 中的重中之重,没有它就寸步难行。

好好练习码力,明年初三了,力争 Ag!

猜你喜欢

转载自blog.csdn.net/Cherrt/article/details/119131629