2025年9月习题集
- P5933 [清华集训 2012] 串珠子。简单的图计数。
- P8329 [ZJOI2022] 树。DP。
- P6646 [CCO 2020] Shopping Plans。堆,最优化。
- P7470 [NOI Online 2021 提高组] 岛屿探险。分治,01-Trie。
- P4809 [CCC 2018] 最大战略储备。最小生成树。
- P7116 [NOIP2020] 微信步数。拉格朗日插值。
- P12486 [集训队互测 2024] 木桶效应。组合数学,DP。
- P9884 [EC Final 2021] Prof. Pang and Ants。二分,贪心。
- 「2021 集训队互测」蜘蛛爬树。分类讨论,李超线段树与合并。
- P3175 [HAOI2015] 按位或。FWT。
- P5643 [PKUWC2018] 随机游走。Min-Max 容斥,DP。
- P4137 Rmq Problem / mex。离线求区间 Mex。
- P9970 [THUPC 2024 初赛] 套娃。ODT。
- GSS2 - Can you answer these queries II。线段树历史最值。
- GSS8 - Can you answer these queries VIII。二项式定理、平衡树。
1. P5933 [清华集训 2012] 串珠子
题目大意:给出邻接矩阵 \(c\),每两个点之间可以连 \(0\sim c_{i,j}\) 条相同的边,问使整张图连通有多少种连边方式,\(n\le 16\)。
设 \(f_{S}\) 表示只考虑集合 \(S\) 的导出子图,连通的方案数,\(g_S\) 则表示不连通的方案数。
考虑 \(g\) 的转移,我们随便找一个点 \(p(p\in S)\),那么剩下的点要么与 \(p\) 连通,要么不连通,枚举 \(S\backslash p\) 的与 \(p\) 连通的子集 \(T\),那么 \(g\) 要加上 \(f_{T\cup p}\times (S\backslash p\backslash T\text{ 随便选的方案数})\)。
那么 \(f\) 用所有方案减去 \(g\) 即可。复杂度为 \(O(3^n)\),瓶颈在于枚举子集。
2. P8329 [ZJOI2022] 树
考虑如果确定了每个点 \(i\) 是否为叶子时如何求方案数,记 \(a_i=0\) 表示在第一棵树中是不是叶子,\(a_i=1\) 则是叶子。
可以 DP,设 \(f_{i,j}\) 表示考虑完前 \(i\) 个点后,指定其中有 \(j\) 个点还需要添加儿子。转移时枚举当前点的父亲是否以后还要添加儿子,则当 \(a_i=0\) 时,\(f_{i,j}=(j-1)f_{i-1,j-1}+jf_{i-1,j}\);当 \(a_{i}=1\) 时,\(f_{i,j}=jf_{i,j}+(j+1)f_{i,j+1}\)。
以上 DP,等价于对所有满足以下条件的序列的 \(\prod _{i=1}^{n-1} b_i\) 求和:\(b_0=b_n=0\)。当 \(a_i=0\) 时 \(b_i=b_{i-1}\) 或 \(b_{i}=b_{i-1}+1\);当 \(a_i=1\) 时 \(b_i=b_{i-1}\) 或 \(b_i=b_{i-1}-1\)。
同时对这个序列计数是可以倒序的,因此设 \(g_{x,i,j}\) 表示考虑完编号在 \(x\) 内的点,第一棵树的 \(b\) 为 \(i\),第二棵树的 \(b\) 为 \(j\) 的答案。
复杂度 \(O(n^3)\)。
3. P6646 [CCO 2020] Shopping Plans
有趣的题。
先考虑如何求某一种商品的前若干种便宜的方案。把商品按价格排序,对于一种方案,可以把它看做从右往左依次把每个商品往右移,且不超过之前移好的商品。因此可以用一个堆维护当前最优的商品,用 \((cnt,at,now,lst,val)\) 表示一个方案,\(cnt\) 商品数,考虑到从右往左第 \(at\) 个商品,当前商品移到了 \(now\),上一个商品移到了 \(lst\),价钱为 \(val\)。
那么从堆中取出一个商品后有三种策略:将当前商品往右移,不能超过 \(lst\);移下一个商品,更新 \(lst\gets now\);在最左侧添加一个商品,要保证所有商品都已经移完。这样我们就能每次 \(O(\log n)\) 得到某个种类的下一便宜的方案。
然后再考虑有多个种类怎么做,类似地我们按顺序依次把每个种类都移好,但是这样我们每次移一个新种类时都至少要移一步,才能保证正确性,所以加入一种操作:若当前种类只移了一步,那么可以撤销这一步,开始移下一个种类,这样就能实现某个种类移 \(0\) 步。
但又有新问题,如何保证撤销后仍满足新的价钱大于当前价钱呢,其实只要把所有种类按第一步的价钱排序即可。
所以有三种策略:当前种类再走一步;下一个种类走一步;若当前种类只走了一步,撤销这一步,下一个种类走一步。
复杂度 \(O(K\log n)\)。
4. P7470 [NOI Online 2021 提高组] 岛屿探险
分类讨论 \(\min(b,d)=b\) 还是 \(=d\)。
\(=b\) 时,把 \(a\) 插入字典树,然后用 \(c\) 查询个数。\(=d\) 时,把 \(c\) 插入字典树,然后用 \(a\) 打加法标记。
那么问题就是在 \(b,d\) 与 \(l,r\) 这两维的偏序上维护数据结构,可以对任意一维分治。
复杂度 \(O((n+q)\log (n\times q) \log V)\)。
5. P4809 [CCC 2018] 最大战略储备
套用克鲁斯卡尔的做法。每次连上某两行之间的所有边,发现这两行就可以看做一行了,且列方向上的每一列连通块个数都会减一。
也就是说每一列的连通块情况都是相同的,行也同理。
那么对行列分别维护并查集与连通块个数即可。复杂度 \(O(n\log n)\)。
6. P7116 [NOIP2020] 微信步数
先判断走不出去的情况,条件就是走完 \(n\) 步还在原地,并且存在一个点使得走 \(n\) 步都不会走出去。
对所有起点同时考虑,计算每一步还有几个点存活。
记 \(l_i,r_i\) 分别为第 \(i\) 维历史走到过的最小位移与最大位移。那么若某个 \(i\) 满足 \(r_i-l_i+1>w_i\),则场上没有点存活。否则第 \(i\) 维有 \(w_i-(r_i-l_i)\) 个点存活,则共有 \(\prod (w_i-r_i+l_i)\) 个点存活。枚举步数可以做到 \(O(nkw)\)。
我们排除掉第一轮,与最后的散轮,发现中间的轮都是类似的。具体来说,记 \(e_i\) 为走完一轮的位移(假设 \(>0\)),那么每轮以后 \(r_i\gets r_i+e_i\)。再探究其中的一轮,记第二轮中第 \(j\) 步以后的历史最大位移为 \(r_{i,j}\),那么新一轮的第 \(j\) 步的历史最大位移就为 \(r_{i,j}\gets r_{i,j}+e_i\)。
那么中间轮的答案即为(记 \(X\) 为中间轮的轮数)
里面是关于 \(i\) 的 \(K\) 次多项式,因此求和后是关于 \(X\) 的 \(K+1\) 次多项式,用朴素算法求出前 \(K+2\) 个值的前缀和,然后用拉格朗日插值代入 \(X\) 即可。最后的散轮也可以暴力算。复杂度 \(O(K^2n)\)。
7. P12486 [集训队互测 2024] 木桶效应
考虑 \(\prod _{i=1}^n(\min_{j=1}^m p_{j,i})\) 的组合意义。即对任意 \(1\le i\le n,1\le j\le m\),满足 \(1\le b_i\le p_{j,i}\) 的序列 \(b\) 的数量。那么算 \(\sum _{p} \prod _{i=1}^n (\min_{j=1}^m p_{j,i})\),就是计算每个 \(b\) 满足条件的 \(p\) 的数量的和。
考虑 \(q=0\)。若确定了 \(b\),我们将 \(b\) 排序,则方案数为 \(\prod_{i=1}^n(i-b_i+1)^m\)。转成 DP,设 \(f_{i,j}\) 考虑到值 \(i\),已经填了 \(j\) 列,转移枚举值 \(i\) 的个数 \(k\),则 \(f_{i,j+k}\gets f_{i-1,j}\times \frac 1{k!}\times \prod_{p=1}^k (j+p-i+1)^m\)。答案为 \(f_{n,n}\times n!\),复杂度 \(O(n^3)\)。
下面是 \(q=0\) 的另一种转移方式与正解。转移分为两部分,首先枚举有 \(k\) 列的值为 \(i\),然后从 \(n-j\) 列中选出 \(k\) 列。第二步乘上分配 \(p\) 的方案数,我们给所有行分配值 \(i\),枚举前 \(b\) 已选了 \(j\) 列,那么每行有 \(j-(i-1)\) 个位置是可选的,则对所有 \(f_{i,j}\) 乘上 \((j-i+1)^m\)。
正解。称有确定值的行或列为特殊行或特殊列。设 \(f_{i,j,S}\) 表示确定了 \(j\) 个普通列与特殊列集合 \(S\)。转移依旧分为两部分,第一部分类比高维前缀和,先固定 \(S\),转移普通列;然后固定普通列,对 \(S\) 做子集和。然后计算排列的方案数,普通行依旧是 \(|S|+j-i+1\) 个位置可选,特殊行若没有确定的 \(i\) 则空位数为普通行空位减去大于 \(i\) 的确定位置;否则为 \(1\)。复杂度 \(O(n^22^q(n+q))\)。
8. P9884 [EC Final 2021] Prof. Pang and Ants
可以二分时间求最多容纳多少蚂蚁。对于一个洞出去的第 \(k\) 只蚂蚁会在 \(a+k\) 时刻到冰箱,进去的倒数第 \(k\) 只蚂蚁会要求在时刻 \(T-a-k\) 及之前到达冰箱。
由于问题是对称的,一个洞只会在前一半时间出蚂蚁,后一半时间进蚂蚁。对于 \(T\) 为奇数的情况,我们让前面最多出两只蚂蚁,中间时刻进出各一只,后面时刻进两只蚂蚁,最后将答案除以 \(2\)。
接下来我们贪心地匹配,每个洞会在一段区间的时刻,每个时刻出蚂蚁,进蚂蚁同理。把区间换成差分,枚举时刻段,同一时刻段的每一时刻可容纳的进出蚂蚁数各是恒定的,维护每个时刻的可容纳进出蚂蚁数与之前时刻段剩下的可容纳出去蚂蚁数即可。
复杂度 \(O(n\log n \log V)\),瓶颈在把时刻排序。将排序换成常数次归并,复杂度 \(O(n\log V)\)。
9. 「2021 集训队互测」蜘蛛爬树
答案为
记 \(l=\text{LCA}(s,t)\),\(d\) 为深度。
第一类,\(x\) 在 \(s\) 子树内,答案为 \(\Delta k\times a_x+2d_x+(s,t)-2d_s\)。
第二类,\(x\) 在 \(l\) 子树外,令 \(y=\text{LCA}(l,x)\),答案为 \(\Delta k\times a_x+2d_x-4d_y+(s,t)+2d_l\)。
第三类,\(y=\text{LCA}(s,x)\) 在 \(s,l\) 的路径上,答案为 \(\Delta k\times a_x+2d_x-2d_y+(s,t)\)。
第一类可以求 \(s\) 子树内所有 \(x\) 组成的凸包,可以合并子树内的李超树。
第二类 \(y\) 在 \(1,l\) 的路径上,树剖后组成了若干重链的前缀,离线下来,对一条重链的每个点维护 \(x\) 在所有轻儿子子树的李超树,然后依次合并扩充前缀;而对于重链方向上的 \(x\),是一个单点的子树内所有 \(x\) 的李超树。而如果最优的 \(x\) 不在我们规定的范围内,此时这个 \(x\) 不优,因此我们这样做是对的。
第三类基本和第二类一样,不同在于最多有一个区间不是前缀,依旧维护轻儿子子树的李超树,把询问区间挂在线段树上的 \(\log\) 个区间询问,自底向上合并线段树上的李超树。
复杂度 \(O(n\log n\log V)\)。
10. P3175 [HAOI2015] 按位或
记 \(f_i\) 为 \(i\) 的期望步数,\(p_{i,k}\) 为选 \(k\) 次后得到 \(i\) 的概率,则
用 FWT 优化掉 \(p\) 的第二维。记 \(P_i\) 为 \(p_i\) 或卷积后的值,\(F_i\) 为 \(i\) 的期望步数 \(f_i\) 经过或卷积后的值。那么
显然 \(0\le P_i\le 1\),当 \(P_i<1\) 其是收敛的,推导式子得
而当 \(P_i=1\) 时原式等于 \(0\)。 复杂度 \(O(2^nn)\)。
11. P5643 [PKUWC2018] 随机游走
记 \(S\) 为包含所有关键点到达时间的集合,我们要求经过所有关键点至少一次的期望时间,即 \(E(\max(S))\)。
根据 Min-Max 容斥得到:
那么 \(E(\min(T))\) 的实际意义就是达到 \(T\) 中任意一个点的期望时间。
考虑 DP 求 \(f_i\) 为点 \(i\) 开始走到确定点集 \(S\) 中任意一个点的期望步数,发现有循环转移,而高斯消元会超时。
考虑待定系数法,把 \(x\) 选为根,然后设 \(f_i=k_if_{fa_i}+b_i\)。解出来 \(b_i,k_i\) 只与 \(i\) 的儿子的 \(b,k\) 有关。而 \(f_x=b_x\)。
对于多次询问,\(T\) 的求和与 \(S\) 无关,预处理子集的高维前缀和即可。复杂度 \(O(n2^n+Qn)\)。
12. P4137 Rmq Problem / mex
考虑按下标顺序建可持久化权值线段树。考虑 Mex 不小于值 \(v\) 的条件,需要满足 \(R\) 及之前最后一个 \(v\) 的位置大于等于 \(L\)。
则每次对 \(a_i=v\),将线段树上 \(v\) 的位置覆盖为 \(i\),维护区间最小值即可。复杂度 \(O(n\log n)\)。
13. P9970 [THUPC 2024 初赛] 套娃
性质:把 \([l,r]\) 的 Mex 放在二维平面上,则平面可以由 \(O(n)\) 个同色矩形划分。构造性证明如下:
我们先对所有前缀求出其 Mex,考虑从小到大依次删掉第 \(i\) 个点。
记 \(nx_i\) 表示 \(i\) 后第一个满足 \(a_j=a_i\) 的 \(j\)。那么所有右端点在 \(nx_i\) 之前的区间都要对 \(a_i\) chkmin。又由于一开始的 Mex 数组是单调递增的,所以可以用 ODT 维护,变化量是均摊 \(O(n)\) 的,获得的矩形个数也是 \(O(n)\) 的。
具体地,维护区间左端点的最小值 \(bg\),右端点所在的区间 \([l,r]\),Mex 的值 \(val\)。在删掉第 \(i\) 个点时,若删去 \((bg,l,r,val)\),则矩形 \([bg,i]\times [l,r]\) 的值为 \(val\)。而 ckmin 的操作可以从 \(nx_i\) 开始从后往前修改。
同时不难发现,以上的做法同时求出极小的 Mex 区间,即上述的 \([i,l]\)。
回到本题,对于 \([l_1,r_1]\times [l_2,r_2]\) 的矩形,会对 \([l2-r1+1,r2-l_1+1]\) 覆盖上 \(val\),差分后,用数据结构维护最小的未出现过的数即可。复杂度 \(O(n\log n)\)。
14. GSS2 - Can you answer these queries II
离线下来以后把询问挂在右端点。枚举右端点 \(i\),对每个 \(l\) 维护 \([l,i]\) 的最值与历史最值。 修改时将 \(l\in (pre_i,i]\) 区间加即可。
15. GSS8 - Can you answer these queries VIII
根据二项式定理
直接在 FHQ_Treap 上维护即可,复杂度 \(O(nk^2\log n)\)。