模拟赛选题
zzy 的金牌
可重集一类的东西是没有顺序之分的,发现 \(K\) 只有 \(300\),所以如果把最终的集合和开始的集合做差,得到一个 \(b\) 数组应该是满足 \(\forall b_i+a_i\ge b_{i-1}+a_{i-1}\) 且 \(\sum b_i=K\) 的。那么我们现在只需 DP 找出 \(b_i\) 的方案数。考虑设 \(f_{i,j,k}\) 表示考虑到第 \(i\) 个数,\(b_i\) 填 \(j\),当前的 \(\sum b_i\) 为 \(k\) 的方案数,转移是显然的。
然后变形一下,发现这个 DP 形式可以差分优化,复杂度就从 \(O(nk^3)\) 变成了 \(O(nk^2)\),可以通过。
口粮输送
赛时不应该去暴力贪心,因为这玩意一看不可贪。考虑到对于一棵树,我们从下往上让所有儿子空余的口粮汇集到父亲,然后根据父亲的口粮剩余情况再层层向上转移,最后只需检查根节点的 DP 值是否非负即可。那么对于一个图而言是同理的,最后走的一定是能够形成最小生成森林的边,那么我们只需找到这个最小生成森林,转移即可。
作弊
原:P7503。
暴力 DP 应该是极其容易的,只需暴力枚举分段即可。
这个 DP 方程很难优化,于是考虑计算每个点的贡献。以每个点 \(i\) 为中心,用树状数组可维护出向左第一个大于等于 \(l_i\) 的位置、第一个大于 \(r_i\) 的位置、向右第一个大于等于 \(l_i\) 的位置、第一个大于 \(r_i\) 的位置。分别记为 \(L_1,R_1,L_2,R_2\)。然后枚举右端点,当右端点位于 \([i,L_2)\) 时,在 \([R_1,L_1]\) 区间统计贡献;当右端点位于 \([L_2,R_2]\) 时,在 \([R_1,j]\) 区间统计贡献。线段树维护全局最大值。
牛仔
原:ARC100D。
不得不说这道题出在考场上的杀伤力巨大,但可以从一些特殊性质入手。\(k>n\) 答案一定是 \(0\),且若 \(A\) 本身就是牛仔序列,那么每一种匹配都是合法的,所以答案为 \((n-m+1)k^{n-m}\)。
考虑到题目中的这个限制比较难以正面处理,所以用总的匹配数减去不合法的匹配数,也就是当这个序列并不是一个牛仔序列时产生的匹配数,等价于这个序列中不存在长度为 \(k\) 的极长不同色连续段。
如果 \(A\) 中有相同元素,我们只关心最左边和最右边的极长不同色连续段大小 \(l,r\),然后 DP,设 \(f_{i,j}\) 表示填了 \(j\) 个元素,当前的极长不同色连续段前缀大小为 \(j\);\(g_{i,j}\) 表示同样条件下的后缀,转移分类讨论插入了和前 \(j\) 个元素同色还是不同色的元素,为
\(g\) 的转移是完全相同的。然后用后缀和优化可以做到 \(O(nk)\) 转移,然后合并时枚举左右两侧分别加入多少个元素。
如果 \(A\) 中没有相同元素,那么一定有 \(m<k\),我们就不关心具体的颜色,因为有引理可得出原序列由不同元素组成长度超过 \(m\) 的段的个数再除以 \(\mathrm A_m^k\) 就是答案,所以只统计原序列中长度为 \(m\) 的不同色子区间个数之和,转移相同,额外地,在 \(j\ge m\) 时 \(g_{i,j}\to f_{i,j}\) 即可。
数数
先考虑如何正着去做,那就是从小到大依次加数,设加入一个数之前的最大连续段长度为 \(L\),那么我们就给 \(F(1),F(2),\dots,F(L)\) 对这个数取 \(\max\) 即可。
那么反过来,如果先给定了 \(F\) 数组,那么相当于指定了加入一部分数之后,最大连续段长度恰好为 \(L\)。考虑通过这个限制进行 DP 转移,那么我们先处理出 \(F\) 数组中的每一个数出现的区间,设其为 \(l_{F(i)}\) 和 \(r_{F(i)}\),然后依然从小到大加数,存储当前的所有连续段,这一点用 \(\tt map\) 套 \(\tt vector\) 即可维护。考虑到如果当前我们要加入的数 \(x\) 在 \(F\) 中出现过,那么此时最大连续段长度一定恰好为 \(r_x\),并且加入它后的最大连续段长度一定恰好为 \(l_x-1\)。反之,如果它没有在 \(F\) 中出现过,那么我们需要保证当前加入的这个连续段不是唯一最长的,转移与上面相同。用这两个条件限制转移即可。转移可以用 \(\tt queue\) 实现。
穿越银匙之门
原:AGC027F。
判断树同构是困难的,考虑如果我们确定一个根,那么判断两棵树同构就只需判断每个节点的父亲即可,判断一个点是否需要操作也只需判断它在两棵树中的父亲是否相同即可。
然后,我们可以从中得到一些约束:
-
若 \(u\) 不需要操作,则 \(\text{fa}_A(u)\) 也不需要操作;
-
若 \(u\) 需要操作,则它必须在 \(\text{fa}_A(u)\) 前操作,在 \(\text{fa}_B(u)\) 后操作。
前者是容易判断的,后者可以建图然后用拓扑排序判断是否是 DAG。
那么现在的问题是如何确定一个根。我们自然是希望找到一个不需要操作的根,但因为有可能所有节点都需要操作,那我们就暴力枚举第一次操作,固定下来一个节点然后以这个节点为根。因为 \(n\) 很小,所以复杂度不成问题。
绳网委托
以 LIS 指代最长不降子序列,考虑转化这个求 LIS 的过程。不难发现,因为我们的序列只有 \(0,1\),所以一个 LIS 必然是由一截子 \(0\) 和一截子 \(1\) 构成。那么,你难道就不更远一点想到,如果我们把序列中每一段的 \(0\) 标记为正数,每一段的 \(1\) 标记为负数,然后找到一段 \(0\) 和一段 \(1\) 的分界点 \(p\)(\(p\) 在 \(0\) 的最后),于是这个 LIS 长度可以转化为 \(\mathit{cnt}+s_p\),其中 \(\mathit{cnt}\) 是 \(1\) 的个数,\(s\) 是刚刚我们标记了正负数的数组的前缀和。
\(\mathit{cnt}\) 是好求的,我们只需找到执行了翻转操作若干次后 \(s_p\) 的最大值。
又注意到,翻转的这些个区间必定是不交的。问题转化为选取一段前缀 和 选取若干段区间,找到它们的最大权值和。
我们可以反悔贪心。具体而言,我们每次去贪心地找最长前缀 和 最大子段和,能保证在当前操作步数下最优。每次操作完,给它们整体乘上 \(-1\),表示以后如果再一次找到了这些区间就可以撤销它们的贡献。不难用线段树维护上述操作,可以看作《山海经》加强版,需要维护区间最大子段和、最小子段和。
落子无悔
如果从上往下贪心,题解告诉我们应该将比较函数定义为 \(\dfrac{p_i}{q_i}>\dfrac{p_j}{q_j}\),其中 \(p_i,q_i\) 分别为 \(i\) 子树中 \(0\) 和 \(1\) 的数量。但是很遗憾,这是痿的,因为取走一个点以后会带来不止一个新的贡献,这些贡献可能使得这个点不再是当前最优。
考虑一个经典的 trick,变成从下往上贪心,依然按照上面的规则比较,每找到一个节点就把它和它父亲合并起来,统计答案。然后这样做就是对的。可以用一个 \(\tt set\) 实现。
体测
先考虑两种部分分。
一种是 \(a_i=1\),首先假设所有区间的右端点不重合,那么对于每个区间只需取到右端点即可满足要求。那么若存在重合的右端点,解决办法也很简单,只需把多余的右端点向左移动,直到所有右端点都不重合即可。移动的过程中需要注意:优先移动左端点更靠左的区间的右端点,以及如果出现右端点小于左端点就直接判断 Sorry。用优先队列实现。
另外一种是 \(a_i\) 互不相同,不难发现此时就是个最小点覆盖,参考 CSP-S 2024 T2。
正解其实就是结合了两种思路。首先对于每一种颜色,跑第一种部分分,其中如果有 Sorry 直接结束,否则就是正常地将每一种颜色的右端点都调整到了互不相同。此时一定有解,我们的目的是用尽可能少的点覆盖所有区间。参考第二种部分分的思路,一定存在一种最优解使得所有的点都取在右端点上,那么我们从左到右枚举所有右端点,提取出包含这个点的所有区间。因为同种颜色的活动一天只能举办一次,所以这个点顶多能覆盖每种颜色的区间各一个。贪心地,我们肯定覆盖右端点最靠左的那一个。然后给这个区间标记为已删除,已删除的区间直接跳过即可。
二分图最大权匹配
原:AGC034D。
此题为 trick 题。第一步,考虑将曼哈顿距离转化为切比雪夫距离,转化方法在此不作赘述。这样我们求的是两个绝对值的最大值,进而拆成四个值的最大值。写一下式子:
考虑费用流。具体地,将四种情况看作四种颜色,将黑点向颜色点连边,颜色点向白点连边,再建立超源超汇连接黑点和白点,跑最大费用最大流即可。
这样做能过原题,在模拟赛题上有 80pts 的高分。发现这个图没有正环,也就是说一次增广必定不会重复经过同一个颜色点。进一步总结出一次增广的流程为:从某一黑点出发找到某一颜色点,然后绕来绕去最终绕到另外某一颜色点,然后从这一颜色点出发找到某一白点。
模拟费用流。可以用堆来维护第一和第三部分的贡献,第二部分的贡献可以用 Floyd 跑最长路求出。实现比较困难,中间用到了多次懒惰删除,即在使用时才删除不符合要求的点。
灯笼
原:P9312 [EGOI 2021] Lanterns / 灯笼。
考虑 DP。设 \(f_{l,r,i}\) 表示当前能到达的海拔区间为 \([l,r]\),当前位置为 \(i\) 的最小花费。转移困难,因为有可能有很多段不相交的山峰的区间,才需要一个 \(i\) 来记录位于哪个区间。于是改为设 \(f_{u,v}\) 表示设当前区间左右端点为 \(a_u\) 和 \(b_v\),不难发现此时的山峰区间就是唯一的。转移时取一个有交的区间进行转移即可。
但此时转移是 \(O(k^2n)\) 的。优化,将 \(u\) 按 \(a_u\) 从小到大枚举,\(v\) 按 \(b_v\) 从大到小枚举。此时如果一个决策点无法转移 \(f_{u,v}\),它也必定无法转移更靠后的 \(f_{u',v'}\)。所以用优先队列维护即可,如果转移堆顶不成就直接 pop 即可。
草莓之歌
原:P9338 [JOIST 2023] 合唱 / Chorus。
首先需要了解 WSQ 二分。这个东西可以在答案关于分段数呈现出凸完全单调性时,解决给定分段数的分段 DP。然后来观察这道题,会发现一个小性质,那就是第 \(i\) 个 \(\tt A\) 与第 \(i\) 个 \(\tt B\) 必定是匹配在一起的。进而考虑一个价值函数 \(w(l,r)\),表示如果将 \([l,r]\) 这个区间的 \(\tt A\) 分为一段所产生的交换次数。不难发现,这个价值为
其中 \(c_i\) 是第 \(i\) 个 \(\tt A\) 前面的 \(\tt B\) 的个数。这个方程的意思也很好理解,就是要统计会和 \(\tt A\) 交换的 \(\tt B\) 的个数。
离能斜率优化的式子已经很近了,考虑去掉 \(\max\)。发现这个 \(c_i\) 是单调不降的,那就很显然,可以用 lower_bound 快速找到第一个 \(k\) 使得 \(c_k-i\ge0\),记为 \(p_i\)。则这个价值函数就变为了
转移方程就是
再设 \(s_i\) 为 \(c_i\) 的前缀和,直接套斜率优化的式子,最终推出
显然 \(i\) 满足单调性,单调队列维护即可。
愤怒的小 L
原:P7468 [NOI Online 2021 提高组] 愤怒的小 N。
首先需要知道这个无穷字符串是怎么构造的,并尝试找到它的通项函数。经过观察,有 \(s_n=1-s_{n-2^m}\),其中 \(m\) 为 \(n\) 的二进制下的最高位。不难发现,\(s_n\) 的取值是由 \(n\) 的二进制位下 \(1\) 的奇偶性确定的。于是得出重要的通项公式:
下文中 \(\operatorname{popcount}(i)\) 简记为 \(\text{P}(i)\)。再用一个公式化掉 \(\bmod2\):
而我们要求的是 \(\sum_{i=0}^{n-1}s_if(i)\)。将刚才求出的 \(s_i\) 的通项公式代入,得
前半部分,我们知道一个 \(k-1\) 次多项式做前缀和后会得到一个 \(k\) 次多项式,即前半部分是一个新的多项式 \(F(i)=\Sigma f(i)\),拉格朗日插值即可求出。
后半部分,并不是很好处理。考虑把 \(f(i)\) 拆开得到
这时考虑将 \(n\) 按 \(\tt lowbit\) 拆开,拆成若干区间,比如 \((1101)_2\) 就会拆成 \([0000,1000),[1000,1100),[1100,1101)\) 这么几个区间。记 \(u\) 为区间左端点,\(t\) 为 \(\log_2(\text{区间长度})\),原式变为
进一步,
此时,注意到一个小性质,那就是 \(u\) 在二进制下的最低位一定高于 \(t\) 在二进制下的最高位,证明显然。那就能得出 \(i\) 在二进制下的最高位也一定低于 \(u\) 在二进制下的最低位。于是说明 \(i+u\) 在二进制下不会产生进位,于是有 \(\text{P}(i+u)=\text{P}(i)+\text{P}(u)\)。于是将 \(\text{P}(i+u)\) 拆开,后面的 \((i+u)^r\) 用二项式定理展开,整理得
发现式子的最后变成了前文某式的子问题:若记
则现在就能得出
考虑计算 \(S(0,t,j)\)。注意到这个式子对于 \(S(0,t,j)\) 其实是不适用的。只能扰动法,最终求出
对于 \(S(2^{t-1},t-1,j)\),可以继续展开。边界条件显然为 \(S(0,0,j)=[j=0]\)。
此时直接算还是不行。但是注意到,当 \(t>j\) 时,\(S(0,t,j)\) 恒等于 \(0\)。于是状态数就减少到了 \(k^3\) 个,就可以直接算了。
对取模后的数进行位运算是愚蠢的。
银行的源起(banking)
考虑只有一个银行的情况,实际上就是树的带权重心。套路地,将贡献拆成每条边的贡献,不难发现答案就是 \(\sum w\times\min(\text{siz}(u),\text{siz}(1)-\text{siz}(u))\)。
现在考虑两个银行。需要发现的是,此时一定存在一条边是没有人走的。考虑枚举这条没有人走的边,则原树断为两棵树,化为两个子问题,采用上文的方法即可。
此时复杂度 \(O(n^2)\)。枚举断边的思路是正确的,考虑优化统计答案的过程。
\(\min\) 很不好处理,于是拆开,每条边 \((u,v)\) 的贡献就化为
其中 \(X\) 就是总的 \(\text{siz}\)。不难发现,此时一棵子树的贡献相当于询问一段 dfn 区间内小于等于某个值的数的贡献和,直接主席树维护 \(w\) 和 \(w\text{siz}(v)\) 即可完成。那么其中一棵子树的答案就完成了,考虑如何计算另一棵子树。发现此时答案受影响的只有 \(1\) 到 \(u\) 这条链上的点,受到的影响就是它们的 \(\text{siz}\) 全部减去了 \(\text{siz}(v)\)。也就是此时的查询变为 \(\text{siz}(i)-\text{siz}(v)\le X/2\)。移项就能避免链减。至于剩下的部分,可以先用主席树查,然后再开一棵线段树维护链,把错误计算的链的部分减去,再加上正确的链的部分,就是答案。
道路修建
加入一条边后,原树变为一棵基环树,环上每个点都对应一棵子树。依然是考虑每条边的贡献:
-
环边:任意不在同一子树内的两点都会经过环边,答案为 \(\dbinom n2-\sum_v\dbinom{\text{siz}(v)}2\);
-
环上其他边:任意不在同一子树内的两点都会经过环上其他边,但没加边前有一遍已经算过了,所以减去:\(\dbinom n2-\sum_v\left(\dbinom{\text{siz}(v)}2+g_v\right)\),其中 \(g_v=\text{siz}(v)\times(n-\text{siz}(v))\);
-
树边:计算总贡献,即从子树内走向子树外,记 \(f_i=\sum_{v\in i}\text{dis}(i,v)\),一棵子树的贡献就是 \(f_i(n-\text{siz}(i))\)。
所以总贡献为
由三部分组成。考虑树剖,每个节点只维护轻儿子的贡献,这样除了 LCA 和链底,剩下的部分都可以直接求了。特殊处理这三个部分,即可。说得云淡风轻,写起来很史。
生命之树
看着很典,积累一下套路。
注意到,一个子树中的点只能和子树外的至多一个点匹配。感性理解。因为数据范围是 \(n^2\) 的,所以直接设 \(f(u,j)\) 表示子树 \(u\) 中,和 \(u\) 匹配的点是 \(j\) 的答案。再设 \(g(u)\) 表示合法的 \(f(u,j)\) 的最小值。这个 \(j\) 实际上并不需要必须在子树外,\(j\) 合法当且仅当 \(\operatorname{dis}(u,j)\le d_u\)。
然后就可以开始 DP 了。对于 \(u\) 的一棵子树 \(v\),有且仅有两种情况:
- \(v\) 子树的所有点全在 \(v\) 子树内匹配,此时 \(v\) 的贡献就是 \(g(v)\);
- \(v\) 子树的点和 \(j\) 匹配,那么提供的贡献就是 \(f(v,j)-c_j\),因为 \(j\) 的贡献我们在 \(u\) 已经算过了。
综上,总的转移方程就是
最终答案为 \(g(1)\)。
染色
其实是比较靠前的一道题,偶然想起就补一下。
这题看着似乎能用树剖等树上数据结构切掉,但你会发现在线区间数颜色暴力维护直接变成 \(O(n^2)\)。仔细想想这玩意常规手段搞不了。发现暴力做的修改 \(O(1)\),查询 \(O(n)\)。所以正解应该是个均摊复杂度,比如定期重构这种。
答案是 bitset。如果我们能把路径上的 bitset 全部或起来,问题自然解决了。但这样做似乎时空都难以承受,至少在时间方面,直接提取出一条路径需要树剖,前面已经讨论过了,不行。于是考虑刻画树上路径的另一种方法,即 LCA。发现我们只需要求出每种颜色是否在路径上只出现一次。考虑改为求 bitset 的异或。这样如果维护从根到 \(u\) 的 bitset,只需用 \(u\) 的 bitset 异或 \(v\) 的 bitset,LCA 及以上的部分就会抵消,路径就刻画出来了。
此时有两个问题:
- 如果给每个点都开一个异或的 bitset,空间复杂度将达到 \(O(\frac{n^2}w)\)。但是现在查询(不考虑带修)很快,是 \(O(\frac nw)\) 的,所以考虑在树上随机撒 \(B\) 个点,这个 \(B\) 可以尽量大一些,然后查询的时候暴力向上跳到第一个被撒的点,这样做期望只需跳 \(O(\frac nB)\) 次,现在单次查询复杂度 \(O(\frac nB+\frac nw)\);
- 带修问题,修一次就需要 \(O(n)\) 的时间。于是定期重构,每 \(\frac nB\) 个修改再重构一次,然后查询的时候再暴力遍历最近的 \(O(\frac nB)\) 个修改,总重构复杂度 \(O(nB)\)。
这个 \(B\) 实测取到 \(w\) 的二倍左右比较快。然后这个题就做完了。
数轴取物
发现每个背包能取的会是一个区间,也就是 \(m\) 个背包会将这个长度为 \(n\) 的序列划分为若干段,不由得有经典 DP:\(f(i,j)\) 表示第 \(i\) 个背包的区间以 \(j\) 结尾的方案数,转移平凡。
现在需要知道 \(g(i,j,k)\) 表示取 \([i,j]\) 区间的物品,背包大小为 \(k\) 时所能得到的最大价值。转移也是平凡的。
然后问题在于第一个转移 \(f\) 的 DP 复杂度是 \(O(n^2m)\),难以通过。但实际上有用的背包至少会取一个物品,所以有用的背包只有 \(n\) 个。因为这题的背包是升序给的,所以只取后 \(n\) 个背包转移即可。总复杂度 \(O(n^3)\)。
排列变环
先从几个特殊性质入手。\(k\le0\) 时答案不是 \(-1\) 就是 \(0\)。现在关注 \(k>0\) 的情况。先考虑 \(w\) 全是正数怎么做。此时一定是一个大环加若干个自环,为了使逆序对数最小,大环上的点一定得是连续的一段,容易得到这样一定不劣。于是双指针即可。
如果 \(w\) 有负数,在取连续的一段的基础上,我们可能需要删掉一些负数。发现一个连续段形成大环,逆序对数是 \(l-1\),其中 \(l\) 是连续段的长度。那么从中删去任意一个中间的数,逆序对数就变成 \(l\)。推广得到删去 \(m\) 个中间的数,逆序对数会变成 \(l-1+m\)。于是我们希望删去最少的数。被删去的数一定是负数,并且是这个区间最负的数。用优先队列可以维护。
补充一句,虽然我们得出的 \(l-1+m\) 个逆序对只会在删除中间的数时成立,但因为删去其他的数的情况也是合法的,所以不用加以特判。
理想路径
对出边进行排序。预处理两个点之间的可达性。对于一组询问,从 \(s\) 出发沿着最小的可达 \(t\) 的点走,此时判环就容易了,统计答案也是容易的。复杂度 \(O(n^2+nq)\),不是正解但是最优解。
字符串
原:P4786 [BalkanOI 2018] Election。
妙在题意的转化。考虑套路地把 C 和 T 变成 \(1\) 和 \(-1\),设区间前缀和为 \(\text{pre}\),区间后缀和为 \(\text{suf}\),不难发现一个 \(O(nq)\) 的贪心:先从左到右扫一遍,遇到前缀和 \(<0\) 就删掉当前字符,累加答案;再从右到左做一遍同样操作。不难发现,形式化地,这样相当于统计了 \(-\text{pre}_{\min}-\text{suf}'_{\min}\),即:前缀和最小值的相反数 + 新后缀和最小值的相反数。之所以是新后缀和,是因为我们在扫第一遍的时候所进行的删字符操作给原后缀和造成了影响。
原前缀和自然不在话下,考虑维护这个新后缀和。为了表述方便,设当前位置为 \(p\)。不难发现,在我们第一遍所做的 \(-\text{pre}_{\min}\) 次操作中,没有影响到原后缀和的操作次数相当于在 \(\boldsymbol p\) 之前的前缀和最小值的相反数,即 \(-\min_{q<p}\text{pre}_q\)。那么,影响到了原后缀和的修改次数就是 \(\min_{q<p}\text{pre}_q-\text{pre}_{\min}\)。
每影响到一次,就会给原后缀和 \(+1\)。所以位置 \(p\) 的新后缀和可以表示为:\(\text{suf}'_p=\text{suf}_p+\min_{q<p}\text{pre}_q-\text{pre}_{\min}\)。
回到我们最开始的答案式,即 \(-\text{pre}_{\min}-\text{suf}'_{\min}\)。它可以最终化为:\(-\min_{p<q}\{\text{pre}_p+\text{suf}_q\}\)。翻译一下,就是区间两个不相交的前缀和与后缀和的最小值的相反数。
这个东西看来无法直接维护,但实际上它就是区间最大子段和 - 区间和。线段树维护就做完了。
汉谟拉比
需要积累的一个套路就是根据期望的线性性,考虑把期望拆成贡献 × 概率。贡献是 \(1\),于是求出概率即可。考虑到这个概率实际上就是每个人分到的钱小于 \(a_i\) 的概率,设 \(x_k\) 为第 \(i\) 组分配的钱,第 \(i\) 个人的概率可以表示为 \(\frac1n\sum_{k=1}^n[x_k<a_i]\)。于是总的答案可以表示为 \(\frac1n\sum_{i=1}^n\sum_{k=1}^n[x_k<a_i]\)。题目最后要求的答案 \(\times n\),于是前面的 \(\frac1n\) 可以省去。
要 DP 这个东西,考虑设 \(f_{i,j}\) 表示考虑到第 \(i\) 组钱,分配了 \(j\) 块的钱。转移时枚举给最后一组分配了多少钱,方程可以自己推。艾佛森括号里的东西可以前缀和处理。
王哥与演出
原:AT_jsc2019_qual_e Card Collector。
这种题型,应当想到的是图论建模。然而直接跑最大费用最大流显然炸了,不妨把每一行和每一列都看作一个点,选物品的过程看作给点和点之间连边。比如在选行的时候把某一列的东西选了,就连一条这一行和那一列之间的边。不难发现最后会连出一个基环森林。考虑如同 Kruskal 的过程一般,用并查集维护连通性,从最大的点开始取。稍有不同的是需要判断一个点是否在环上以及只能在一个环上,然后就做完了。
最小字典序
正解其实比较暴力。不难想到用 basic_string 暴力 DP 可以做到 \(O(n^3)\) 复杂度。发现有一个 \(n\) 是在比较上,所以改用二分哈希比较,复杂度降到 \(O(n^2\log n)\)。考虑优化。首先可以用倍增取代二分,这样在查询时间不变的情况下空间被优化到 \(O(n\log n)\)。然后发现原本单次需要 \(O(n)\) 转移,但是注意到 \(\bigvee_{k=i}^ja_k\) 这一段一定是 \(\le a_i\) 最优,所以我们需要考虑的状态是有限的;同时我们需要维护的是一个后缀最小值状物,所以单调栈优化,查询的时候在单调栈上二分。
狼群
首先,你须记住:从 \((0,0)\) 走恰好 \(m\) 步到 \((x,y)\) 的方案数是
所以本题第一个式子就是
容易发现,绝对值不影响计算,可以拆掉。式子化为
发现只和 \(\frac{x'+y'}2\) 与 \(\frac{x'-y'}2\) 有关,且和每个 \(x',y'\) 一一对应。所以改为枚举这个。变成
然后你会发现可以把 \(x'\) 和 \(y'\) 分开考虑了,变为
做完了。

浙公网安备 33010602011771号