历年各赛事真题选做(二)
历年各赛事真题选做(二)
\(\newcommand \oper \operatorname\)\(\newcommand \seq \mathcal\) \(\newcommand \m \mathbf\)\(\newcommand \txt \texttt\)
\(\text{By DaiRuiChen007}\)
推荐阅读:
- I. [IOI 2022] 最罕见的昆虫
- L. [eJOI 2018] 循环排序
- O. [USACO 2021.1] Minimum Cost Paths
- U. [联合省选 2022] 序列变换
A. [八省联考 2018] 林克卡特树
注意到题目等价于在一棵树上选出恰好 \(k+1\) 条点不交的链,并最大化所有链的权值和
考虑 wqs 二分,每选出一条新的链就赋 \(\Delta\) 的额外权值,树形 dp 算出取得最大权值时分割的链数,二分 \(\Delta\) 即可
树形 dp 时记录每个点是单链还是链的 LCA,分别记为 \(dp_{u,1},dp_{u,2}\) 转移即可
时间复杂度 \(\mathcal O(n\log V)\),其中 \(V=\sum |v_i|\)
B. [国家集训队] Crash 的文明世界
先考虑 \(k=1\) 的情况,我们只需要换根 dp 即可,但当 \(k>1\) 时,换根的转移需要我们从 \(\sum_v\oper{dist}(u,v)^k\) 快速转移到 \(\sum_v(\oper{dist}(u,v)+1)^k\),用二项式定理展开,维护 \(0\) 次方和到 \(k\) 次方和,单次转移需要 \(\mathcal O(k^2)\) 的时间复杂度,无法通过此题
考虑优化,注意到问题主要在 \((x+1)^k-x^k\) 不好维护,考虑下降幂的性质:\((x+1)^{\underline k}-x^{\underline k}=k\times x^{\underline{k-1}}\),这样维护 \(\sum_v \oper{dist}(u,v)^{\underline 0}\sim\sum_v \oper{dist}(u,v)^{\underline k}\),即可做到 \(\mathcal O(k)\) 转移
最后求答案时用一般幂的展开公式 \(x^k=\sum_{i=0}^k \begin{Bmatrix}i\\k\end{Bmatrix}x^{\underline i}\),预处理出第二类斯特林数的前 \(k\) 行即可
时间复杂度 \(\mathcal O(k^2+nk)\)
C. [NOI 2020] 美食家
考虑作出邻接矩阵,用 \((\max,+)\) 卷积求出邻接矩阵的 \(T\) 次方,但我们发现边权的限制很难处理,于是考虑拆点,在一条长度为 \(w_i\) 的边中间插入 \(w_i-1\) 个节点,但这样显然会超时,考虑对每个节点 \(u\) 拆点,用状态 \((u,t)\) 表示 \(t\) 天后能到达 \(u\),然后直接矩阵快速幂优化即可
但注意到此时的时间复杂度是 \(\mathcal O((nw)^3k\log T)\) 会超时,注意到不需要计算出邻接矩阵,我们只需要求出从 \(1\) 开始到每个状态的权值即可,因此考虑优化成向量左乘转移矩阵的形式,因此我们预处理出转移矩阵的 \(2^t\) 次方,每次只需要用向量乘转移矩阵即可
时间复杂度 \(\mathcal O((nw)^3\log T+(nw)^2k\log T)\)
D. [联合省选 2020] 作业题
考虑先推式子,设 \(f(d)\) 表示 \(\gcd(w_{e_1},w_{e_2},\dots ,w_{e_{n-1}})=d\) 的方案数,显然答案即为 \(\sum_{d=1}^\infty d\times f(d)\),考虑莫比乌斯反演,记 \(g(d)\) 表示 \(d\mid\gcd(w_{e_1},w_{e_2},\dots,w_{e_{n-1}})\) 的方案数,显然有 \(g(n)=\sum_{n\mid d}f(d)\),莫比乌斯反演得 \(f(n)=\sum_{n\mid d} g(d)\times\mu(\frac dn)\),因此我们只需要求每个 \(g(n)\),就可以在 \(\mathcal O(n\ln n)\) 的时间复杂度内反演得到 \(f(n)\)
显然求 \(g(d)\) 只需要把 \(d\mid w_{i}\) 的每个 \(w_i\) 加入边集 \(\m E_d\),然后求 \(\m G_d=(\m V,\m E_d)\) 的生成树边权之和,显然生成树的边权积之和可以直接用矩阵树定理,考虑构造二项式 \(w_ix+1\) 作为新的边权,在 \(\bmod x^2\) 意义下求出其 Kirchoff 矩阵 \(\m L_d\) 的行列式值,其常数项系数即为答案
注意到此时的时间复杂度为 \(\mathcal O(wn^3)\),但显然对于很多 \(d\),其 Kirchoff 矩阵不是满秩的,此时无法找到生成树,\(g(d)=\det(\m L_d)=0\),可以直接判掉,先用并查集判断图是否联通再求 \(\oper{det}(\m L_d)\)
由于每条边至多出现在 \(\sqrt w\) 个 \(\m G_d\) 中,而 \(g(d)\) 有意义必须保证 \(|\m E_d|\ge n-1\),因此有意义的 \(d\) 只有 \(\mathcal O \left(\dfrac{m\sqrt w}{n}\right)\) 个,因此时间复杂度为 \(\mathcal O(n^2m\sqrt w)\)
E. [清华集训 2016] 如何优雅地求和
注意到一般多项式 \(f(k)=\sum_{i=0}^m a_ix^i\) 和组合数复合的形式很难处理,考虑转成下降幂多项式 \(f(k)=\sum_{i=0}^m b_ix^{\underline i}\) ,推式子得到:
因此我们可以 \(\mathcal O(m\log m)\) 计算答案,我们只需要找到多项式点值 \(c_0\sim c_m\) 和下降幂多项式 \(b_0\sim b_m\) 的快速转化,推式子得到:
因此 \(b_i\) 的 OGF 可以看成 \(c_i\) 的 EGF 乘上 \(e^{-x}\) 得到,因此一遍 NTT 即可解决下降幂多项式和点值的转化
时间复杂度 \(\mathcal O(m\log m)\)
F. [HAOI 2015] 按位或
对每个数位 \(i\) 分别考虑,设 \(x_i\) 表示你的当前数字 \(N\) 的第 \(i\) 位变成 \(1\) 的时刻,把每个二进制数 \(S\) 看成一个集合 \(\{x_i\mid \oper{digit}(S,i)=1\}\)
设全集为 \(\m A\),答案等价于求 \(E(\max\{\m A\})\),做 min-max 容斥即得 \(E(\max\{\m A\})=-\sum_{\m S\subseteq\m A}(-1)^{|\m A|}E(\min\{\m S\})\)
考虑 \(E(\min\{\m S\})\) 的组合意义,即 \(N\oper{ and }S\ne0\) 的期望用时,考虑反面考虑,显然有 \(E(\min\{\m S\})=(1-\sum_{\m T\cap\m S=\varnothing}p_T)^{-1}\),因此用子集求和处理出 \(\oper{sum}(T)=\sum_{\m S\subseteq \m T} p_S\),那么 \(E(\min\{\m S\})=(1-\oper{sum}(\m A-\m S))^{-1}\),直接计算即可
时间复杂度 \(\mathcal O(n2^n)\)
G. [COCI 2019] Akvizna
考虑朴素 dp,设 \(dp_{i,j}\) 表示还剩 \(j\) 轮比赛时还有 \(i\) 个人的最大得分,转移为 \(dp_{i,j}=\max_{k<i}\left\{dp_{k,j-1}+\dfrac{j-k}{j}\right\}\)
设 \(F(k)\) 为进行 \(k\) 轮比赛的答案,即 \(dp_{n,k}\),可以证明 \(F(k+1)-F(k)\le F(k)-F(k-1)\),因此考虑 wqs 二分,每操作多一轮就附加上 \(-\Delta\) 的得分
此时设 \(dp_i\) 表示还剩 \(i\) 个人时的最大的分转移为 \(dp_i=\max_{j<i}\left\{dp_{j}+\dfrac{i-j}i-\Delta\right\}\),容易证明转移代价函数 \(\oper{cost}(i,j)=1-\dfrac ji-\Delta\) 满足四边形不等式,因此可以二分维护转移点的单调队列求解
时间复杂度 \(\mathcal O(n\log n\log k)\)
H. [HNOI 2015] 开店
由于题目要求强制在线,因此考虑点分树,对于每个 \(u\),设其在点分树中的子树为 \(\oper{subtree}(u)\),在点分树中的父亲为 \(\oper{fa}(u)\),对于每个 \(v\in\oper{subtree}(u)\) 以 \(x_v\) 为下标在线段树上记录 \(\oper{dist}(u,v)\) 的值,同时在第二棵线段树上记录 \(\oper{dist}(\oper{fa}(u),v)\) 的值,以便在统计经过 \(\oper{fa}(u)\) 的路径时容斥掉已经在 \(u\) 处统计过的路径
每次查询计算 \(u\) 在点分树每个祖先对应线段树上 \([L,R]\) 的区间和,然后容斥一下已经在儿子处算过的路径即可
注意本题如果直接用动态开点线段树可能会被卡常,实际实现可以以 \(x\) 为关键字排序预处理前缀和,用 vector
维护,查询时二分出左右端点求前缀和即可
时间复杂度 \(\mathcal O(n\log^2 n)\)
I. [IOI 2022] 最罕见的昆虫
首先考虑一个简单问题:如何求出颜色的种数,考虑如下的过程:
- 遍历每个元素 \(i\),把 \(i\) 加入机器中,查询当前机器中的众数 \(m\)
- 若 \(m=1\):说明当前元素是新的,保留
- 若 \(m>1\):说明当前元素有重复,删除
可以通过归纳法证明任何时候机器中每种颜色的元素都有且仅有一只,因此最终机器中元素的数量 \(C\) 就是颜色数
因此考虑二分,颜色最少的出现次数 \(k\),用类似的方法维护使得机器中每种元素的出现次数都 \(\le k\),最终我们可以用机器中留下的元素总数是否是 \(k\times C\) 来判断
但这样的操作次数是 \(\mathcal O(n\log n)\) 的,不够优秀,考虑剪枝:
- 对于某个 \(k\),若最终机器里有 \(k\times C\) 个元素,可以不删除,只要在后续过程中不考虑这些元素即可,否则当前时刻不在机器里的元素可以直接不予考虑
注意到此时还需要处理的元素大约是原来的 \(\dfrac 12\),算上求 \(C\) 的代价,总操作次数大约是 \(n+n+\dfrac n2+\dfrac n4+\dots\approx 3n\) 的
但由于二分不一定能实际达到这个界,可能会被精心构造的数据卡掉,因此我们可以考虑随机优化:每次二分某个 \(k\) 之前随机重排一下插入待处理元素的顺序,就可以通过此题
时间复杂度 \(\mathcal O(n\log n)\)
J. [BJOI 2018] 链上二次求和
考虑先把贡献拆分到单点上,然后把长度为 \([L,R]\) 的限制用前缀和转成区间长 \(\le x\),对于每个 \(i\),只需要计算经过 \(i\) 且长度 \(\le x\) 的区间个数即可
- 当 \(x\ge n\) 时:任何一个 \(i\) 的答案都是 \(i\times (n-i+1)\)
- 当 \(x<n\) 且 \(2x\ge n\) 时:
- 若 \(1\le i\le n-x\):答案为 \(x+(x-1)+\cdots+(x-i+1)=\dfrac {i\times(2x-i+1)}2\)
- 若 \(n-x<i\le x\):答案为 \((n-i+1)\times (x-n+i)+(n-i)+(n-i-1)+\dots+(x-i+1)=-i^2+(n+1)i-\dfrac{(n-x)(n-x+1)}2\)
- 若 \(x<i\le n\):答案为 \(x+(x-1)+\dots+(x-n+i)=\dfrac{(n-i+1)(2x-n+i)}2\)
- 当 \(2x<n\) 时:
- 若 \(1\le i\le x\):答案为 \(x+(x-1)+\cdots+(x-i+1)=\dfrac {i\times(2x-i+1)}2\)
- 若 \(x<i\le n-x\):答案为 \(x+(x-1)+\dots +1=\dfrac{x(x+1)}2\)
- 若 \(n-x<i\le n\):答案为 \(x+(x-1)+\dots+(x-n+i)=\dfrac{(n-i+1)(2x-n+i)}2\)
容易发现,若视 \(n,x\) 为参量,那么每个 \(i\) 对答案的贡献够可以写成关于 \(i\) 的二次函数的形式,用线段树维护 \(\sum w_i,\sum i\times w_i,\sum i^2\times w_i\) 即可
时间复杂度 \(\mathcal O(n\log n)\)
K. [联合省选 2021] 图函数
考虑某一对点 \((u,v)\) 的贡献,首先,我们要找到一条路径 \(u\to v\) 满足路径中所有点的标号都 \(\ge u\),在这个基础上,有贡献的一定是路径上边标号最小值最大的路径
设 \(u\to v\) 路径上最大的最小标号为 \(\oper{val}(u,v)\),那么 \(u\to v\) 对所有 \(h(\m G_{\oper{val}(u,v)})\sim h(\m G_m)\) 都有贡献,Floyd 维护 \(\oper{val}(u,v)\),转移时倒序枚举中转点保证路径中节点标号的限制即可
时间复杂度 \(\mathcal O(n^3+m)\)
L. [eJOI 2018] 循环排序
先考虑排列的情况:首先假设不存在 \(p_i=i\) 的情况,显然的想法是对所有 \(i\to p_i\) 连边,显然可以通过一次操作复原一个环,因此我们证明了此时 \(\sum k\) 的最小值是 \(n\),但此时 \(q=c\),其中 \(c\) 是环的数量
考虑 \(s=\infty\) 的时候有什么优化策略:考虑把所有的环连在一起,那么在一次操作之后,每个环有且仅有一个节点未复位,且这些未复位的节点恰好构成了一个新的环,此时我们构造了一个 \(2\) 次操作,共操作 \(n+c\) 个元素的方案
若加入 \(s\) 的限制,那么我们可以考虑选出 \(\min(s-n,c)\) 个环,用上面的操作 \(2\) 次复原,剩下的每个环暴力复原,容易证明当 \(\min(s-n,c)>2\) 时这种策略更优
如果存在 \(p_i=i\) 的情况也是 trivial 的,注意到这些位置已经复原,直接从原序列中删掉即可
接下来考虑非环的情况:我们只需要确定出每个 \(i\) 最终还原到哪个位置 \(p_i\),显然存在一个区间限制 \(l_i\le p_i\le r_i\),先考虑 \(i\in[l_i,r_i]\) 的情况,此时直接让 \(p_i=i\) 一定不劣,对于剩下的节点,我们连接所有 \(i\to j(j\in[l_i,r_i])\),那么我们需要把整个图分解成若干个哈密顿回路
回到排列的情况,容易发现 \(c\) 越小答案一定更少,因此我们只需要最小化 \(c\),我们猜测任意一个连通分量一定可以写成恰好一个哈密顿回路,不过找哈密顿回路的复杂度较高,难以接受
不过注意到对于 \(a_i\) 相同的点,其对应的 \([l_i,r_i]\) 也相同,我们实际上是在找他们的一个匹配,考虑用下图的方式优化建图,即我们把颜色 \(a_i\) 建立虚点:
上图中:我们用同色的节点表示 \(a_i\) 相同的位置,用对应颜色的矩形表示该 \(a_i\) 对应的区间 \([l_i,r_i]\),那么我们只需要在新的图上找到一条欧拉回路即可,但进一步注意到每个节点实际上只有一条入边和一条出边,因此每个节点其实可以抽象成连接两个虚点的一条边,因此我们只需要把所有颜色对应的虚点连起来,找到一条欧拉回路,然后根据其边的访问顺序还原出 \(p_i\),由于图中每个节点一定保证入度等于出度,因此这样的欧拉回路总是存在
因此我们可以通过优化建图找欧拉回路的方式把每个联通分量对应到一个环上,可以证明不存在比这更优的做法,因此直接求欧拉回路,然后将每条边 \(i\) 的目标 \(p_i\) 指向其在欧拉回路中的下一条边的编号,再用排列的情况求解即可
时间复杂度 \(\mathcal O(n\log n)\),瓶颈在于排序和离散化
M. [联合省选 2021] 滚榜
显然答案只和读名字的顺序有关,并且我们只需要记录当前最后一个读名字的队伍即可转移,设 \(dp_{i,\m S,c,j}\) 表示 \(\m S\) 内的选手已经完成滚榜,最后一个滚榜的 \(b_i=j\),且 \(b_i\) 总和为 \(c\),转移时枚举下一只滚榜的队伍,时间复杂度为 \(\mathcal O(2^nn^2m^2)\) 考虑优化
那么每次从 \(i\) 转移到 \(k\) 的时,有 \(b_k\ge \max(b_{i},a_i+b_i-a_k+[i<k])=b_i+\max(0,a_i-a_k+[i<k])\)。因此我们发现 \(b_i\) 数组的差分是可以求出来的,因此对于一个 \(i\to k\) 的额外代价 \(\oper{cost}(i,k)=\max(0,a_i-a_k+[i<k])\) 会对后面的 \(n-|\m S|\) 次转移都产生贡献,因此我们不需要记录 \(j\),而是在每次转移的时候考虑完 \(\oper{cost}(i,k)\) 对后续的所有贡献,因此转移时时枚举 \(k\not\in\m S\) 有 \(dp_{k,\m S+k,c+(n-|\m S|)\oper{cost}(i,k)}\gets dp_{i,\m S,c}\)
时间复杂度 \(\Theta(2^nn^2m)\)
N. [SCOI 2016] 幸运数字
考虑点分治维护路径信息,把所有询问 \((u,v)\) 离线到 \(u\) 和 \(v\) 上,然后对整棵树进行点分治,对于某个点分治重心 \(\oper{root}\),对于子树中每个 \(u\) 维护 \(u\to \oper{root}\) 路径上点权构成的线性基,当发现某对 \((u,v)\) 此时分属 \(\oper{root}\) 的两棵子树时,就把 \(u\) 和 \(v\) 对应的线性基合并起来,然后求出答案即可
时间复杂度 \(\mathcal O(n\log n\log V+q\log^2V)\),其中 \(V\) 为 \(G_i\) 的值域
O. [USACO 2021.1] Minimum Cost Paths
注意到第二档部分分非常有趣,考虑从这一档部分分入手,可以发现最优路径一定只会在第 \(1\) 和第 \(y\) 列往下走,否则把这一段向下走的替换到第 \(y\) 列一定不劣,因此只需要最开始在第 \(1\) 列走到了哪一行
假设整条路径为 \((1,1)\to(p,1)\to(p,y)\to(x,y)\),那么相应的代价应该是 \((p-1)\times c_1+(y-1)\times p^2+(x-p)\times c_y\)
容易发现这个代价是关于 \(p\) 的二次函数 \(f(p)=(y-1)\times p^2+(c_1-c_y)\times p+xc_y-c_1\),最小值在 \(p=\dfrac{c_y-c_1}{2(y-1)}\) 处取得,由于 \(p\) 是整值,因此四舍五入到 \(\left\lfloor\dfrac{c_y-c_1}{2(y-1)}\right\rceil\) 处(\(\left\lfloor x\right\rceil\) 表示 \(x\) 四舍五入到最近整数的结果)
同理,根据上面一部分的启发,我们发现,对于任意两列 \(y_1,y_2\) 我们应该在第 \(\left\lfloor\dfrac{c_{y_1}-c_{y_2}}{y_1-y_2}\right\rceil\) 行转移,简记为 \(P(y_1,y_2)\)
那么我们可以猜想,(忽略 \(x\) 的限制)任何一组 \(1\to y\) 的最优解一定是经过若干个 \(y_1,y_2,\dots y_k\) ,其中从任意 \(y_i\to y_{i+1}\) 均选择路径 \(P(y_i,y_{i+1})\),因此可以考虑对 \(y\) 离线,用单调栈维护当前转移路径上所有的 \(y_i\),压入新的 \(y\) 的时候按 \(P(y_{i-1},y_i)\ge P(y_i,y)\) 更新整个单调栈即可,这一步的贪心策略的正确性可以用调整法证明
接下来考虑横向这一维的限制,首先我们发现 \(P(y_1,y_2)\) 首先要调整到 \([1,n]\) 之间,在计算的时候取一下 \(\min\) 和 \(\max\) 即可,而对于每次询问的 \(x\) 限制,我们可以在单调栈上二分找到最后一段 \(P(y_{i-1},y_i)\le x\) 的转移,而剩下的一定要尽可能靠近二次函数对称轴,即贴近 \(x\) 更优,因此在维护单调栈的时候顺便维护到每个 \(y_i\) 的前缀距离即可直接计算
时间复杂度 \(\mathcal O(q\log m)\)
P. [GXOI 2019] 旅行者
一个显然的想法是建立虚源点汇点 \(S,T\),对于每个关键点 \(u\),连接 \(S\to u,u\to T\) 边权都为 \(0\),然后统计 \(S\to T\) 的最短路
但这种情况的问题是可能会出现 \(S\to u\to u\to T\) 的最短路影响答案,因此我们假设某次和 \(S\) 相连的顶点集为 \(\m S\),与 \(T\) 相连的顶点集为 \(\m T\),那么我们应该保证 \(S\cap\m T=\varnothing\),但我们又要保证对于每一对关键点 \((u,v)\),都必须有 \(u\in \m S,v\in \m T\) 这样才能统计所有点对的贡献
此时考虑二进制分组,也就是对于每个二进制位 \(d\) 分别考虑,对于每个关键节点 \(u\) 若 \(u\) 的二进制第 \(d\) 位为 \(0\) 则 \(u\in\m S\),否则 \(u\in\m T\) 求出 \(S\to T\) 的最短路,然后交换 \(\m S,\m T\) 再求一遍
可以证明这个做法统计了所有需要统计的点对 \((u,v)\) 且没有统计自环的情况 \((u,u)\):
对于某对 \((u,v)\),由于 \(u\ne v\),因此 \(u\oplus v\ne 0\),考虑 \(\oper{lowbit}(u\oplus v)\),显然在这一位 \(u,v\) 会被划分到 \(\m S,\m T\) 两个不同的集合中,得证
因此我们二进制分组求 \(\log k\) 次最短路即可
时间复杂度 \(\mathcal O(m\log m\log k)\)
Q. [联合省选 2020] 组合数问题
同样是一般多项式和组合数的复合问题,考虑用下降幂多项式 \(\sum_{i=0}^m b_i\times x^{\underline i}\) 表示 \(f(x)\),推式子得到:
而 \(f(x)=\sum_{i=0}^m a_ix^i\) 到 \(f(x)=\sum_{i=0}^m b_ix^{\underline i}\) 的转化也是显然的:
因此 \(b_k=\sum_{i=k}^m a_i\begin{Bmatrix}i\\k\end{Bmatrix}\),预处理出第二类斯特林数直接计算即可
时间复杂度 \(\mathcal O(m^2+m\log n)\)
R. [APIO 2021] 封闭道路
考虑朴素的 dp,设 \(dp_{u,0/1}\) 表示以 \(u\) 为根的子树,当前 \(u\) 的度数为 \(k/k-1\) 的最小代价,对于每个 \(u\),我们先将其儿子 \(v\) 的 \(dp_{v,1}\) 加入统计,然后取出最小的 \(\oper{deg}(u)-k\) 个 \(w(u,v)+dp_{v,0}-dp_{v,1}\) 表示这些 \((u,v)\) 的边被切断,把答案统计进 \(dp_{u,0}\),而 \(dp_{u,1}\) 则要把第 \(\oper{deg}(u)-k+1\) 个 \(w(u,v)+dp_{v,0}-dp_{v,1}\) 也统计到其中
此时暴力用堆维护,时间复杂度 \(\mathcal O(n^2\log n)\),考虑优化
注意到对于某个节点 \(u\) 若当前的限制 \(k\) 满足 \(\deg(u)\le k\),那么我们可以直接不考虑这个节点,因为 \(u\) 的所有出边都可以被保留,即删除 \(u\) 和 \(u\) 的出边,直接把 \(w(u,v)\) 插入 \(v\) 对应的堆里,然后继续在剩下的森林用上述做法进行 dp
不过 dp 完成后注意堆不能直接清空,而是要记录插入和删除操作然后逐步撤销,以防把一些被删除的 \(u\) 对应的权值 \(w(u,v)\) 给删掉
注意到 \(\sum \oper{deg}(u)=2n-2\),因此 \(n\) 轮 dp 考虑的点的总数是 \(\mathcal O(n)\) 的,可以通过本题
时间复杂度 \(\mathcal O(n\log n)\)
S. [HNOI 2018] 毒瘤
先考虑 \(m=n-1\) 的情况,即树上独立集计数,显然 \(dp_{u,0}=\prod (dp_{v,0}+dp_{v,1}),dp_{u,1}=\prod dp_{v,,0}\)
注意到 \(t=m-n+1\) 的值很小,这启示我们建出生成树后枚举这 \(t\) 条自由边的分配情况,考虑 \((*,0),(0,1)\) 两种情况,每次做一遍树形 dp 即可,时间复杂度 \(\mathcal O(2^tn)\),无法通过此题
考虑优化,注意到这 \(2^t\) 种状态始终只影响这 \(\mathcal O(t)\) 个端点到根的 dp 值,因此考虑建出虚树,用类似动态 dp 的方式求出 \(u\) 到其虚树上父亲 \(\oper{fa}(u)\) 的转移矩阵,每次树形 dp 只要在虚树上转移即可
时间复杂度 \(\mathcal O(n+t\times 2^t)\)
T. [JSOI 2018] 潜入行动
简单 dp,设 \(dp_{u,i,0/1,0/1}\) 表示以 \(u\) 为根的子树,用了 \(i\) 个设备,其中 \(u\) 有没有装设备,\(u\) 有没有被监听到的方案数
转移时用一个类似树上背包的形式分讨转移,注意优化树上背包的转移上界
时间复杂度 \(\mathcal O(nk)\)
U. [联合省选 2022] 序列变换
考虑把括号序列变成树,点权挂到节点上,那么每次操作相当于找到某对兄弟节点 \(u,v\),然后把 \(v\) 和 \(v\) 的每一棵子树挂到 \(u\) 的儿子上,代价为 \(xw_u+yw_v\),目标就是把整棵树变成一条单链
考虑忽略树的形态,转而分层考虑,那么每个操作相当于把某一层的两个节点 \(u,v\) 中的一个放到下一层,代价为 \(xw_u+yw_v\),最终使每层有且仅有一个节点
但是这不一定保证了 \(\oper{fa}(u)=\oper{fa}(v)\),但是我们可以证明存在一种最优解使得我们第一层开始依次还原,那么此时 \(u,v\) 所在层的上一层有且仅有一个节点,那么这个操作必然是合法的,因次这样的转化是合理的
考虑当前层剩余的节点构成的集合为 \(\m S\)
接下来分类讨论四种情况:
-
\(x=0,y=0\)
答案直接为 \(0\)
-
\(x=0,y=1\)
显然留下 \(\max\{\m S\}\) 的节点即可
-
\(x=1,y=1\)
考虑依然每层留下 \(\max\{\m S\}\),先把 \(\m S\) 中其他节点通过 \(\min\{\m S\}\) 转移到下一层,而 \(\min\{\m S\}\) 最后通过 \(\max\{\m S\}\) 转移到下一层
由于每个节点都至少会成为一次用来被他人转移的 \(xw_u\)(最后一层的节点的贡献只有 \(yw_v\),但也可以等效一下)因此每层留下任何一个节点用来转移 \(\min\{\m S\}\) 都一样
-
\(x=1,y=0\)
注意到此时肯定是继续用 \(\min\{\m S\}\) 转移,但最后在该层留下的应该是 \(\oper{sec-max}\{\m S\}\)(即次大值),因为最终把全局最大值放到最底下反而更优,因为此时不用支付最后一层节点的转移代价,需要注意的是 \(|\m S|=2\) 的情况
- 若此时已经到最后两层:则直接用较小的节点把大的转移到下面去
- 否则一定是形如一条链中间额外挂一个节点的情况,把这样的整条链提取出来,容易发现这个整体只会留下一个元素,并且一定是链上的最大值或最小值,枚举两种情况分别处理即可,可以证明在这条链结束以后后面任何时候都有 \(|\m S|>2\)(倒数第二层除外),因此保证了只用枚举两种情况
时间复杂度 \(\mathcal O(n\log n)\)
V. [HNOI 2017] 大佬
考虑一个显然的 dp,状态 \((i,m,f,l,c)\) 表示前 \(i\) 天你还剩 \(m\) 点自信,你的等级和攻击分别是 \(f,l\),对手还剩 \(c\) 点自信
但这个状态太大了,注意到和 \(i\) 有关的只有每天生命值的变化,因此我们可以把 \((i,c)\) 分离出来,用一个简单的 dp 处理出想要存活到第 \(i\) 天,至少要有几天拿来自我恢复,求出自由行动的最大天数
接下来考虑普通攻击,显然知这是 trivial 的,我们只需要在用剩下四种操作之余攻击即可
因此重点来到了状态 \((F,L)\),考虑对于每个 \(L\) 处理出至少需要几天才能造成这么多伤害,把 \((F,L)\) 打包 BFS 即可,发现此时不同 \(L\) 状态的数量 \(S\) 的上界不大用,哈希表记录即可(实际数据中 \(S\) 只有 \(1.2\times 10^6\) 级别)
接下来考虑处理询问,显然我们得到造成每个伤害 \(L\) 的最小天数 \(D_L\),对于不使用 \(L\) 和只用一次 \(L\) 的情况都是 trivial 的,而对于使用两次 \(L\) 的情况要求 \(C-(D-D_{L_1}-D_{L_2})\le L_1+L_2\le C\),其中 \(D\) 表示最大的自由天数,对 \(L\) 一维双指针扫描即可
时间复杂度 \(\mathcal O(wS+S\log S+mS)\)(其中 \(w=\oper{mc}\))
W. [HAOI 2018] 反色游戏
把每条边看成一个 \(0/1\) 变量解这个异或方程组,容易证明:当一个连通块的节点颜色异或和不为 \(0\) 必然无解,否则任意一棵生成树都有唯一解,因此一个连通块的自由元数量为 \(m-(n-1)\),解总数为 \(2^{m-(n-1)}\),整张图的解数为 \(2^{m-(n-k)}\),其中 \(k\) 为连通块数量
维护每个节点是不是割点,然后对割出来的连通块分别讨论有没有解即可
时间复杂度 \(\mathcal O(n+m)\)
X. [HNOI 2013] 切糕
考虑最小割模型:建一层虚拟节点 \((x,y,0)\),然后连接 \(S\to (x,y,0) =\infty\),\((x,y,z-1)\to(x,y,z)=v(x,y,z)\),\((x,y,r)\to T=\infty\),此时任意 \(z\) 相同的一列都至少要割掉一条边
为了保证 \(|f(x,y)-f(x',y')|\le d\),我们可以考虑连边 \((x,y,z)\to (x',y',z-d)=\infty\),此时若 \(f(x',y')<z-d<z<f(x,y)\),则会产生 \(\infty\) 的流量,交换 \((x,y),(x',y')\) 能够得到相反符号的结果,因此能够保证任何 \(f(x,y)-f(x',y')\in[-d,d]\)
直接求出网络上的最大流即可
理论时间复杂度 \(\mathcal O(p^3q^3r^3)\) 但足以通过此题
Y. [JXOI 2017] 颜色
考虑哈希,给每个位置随机赋值,然后通过调整把使得同颜色所有位置异或和为 \(0\),然后只需要统计有多少个哈希值异或和为 \(0\) 的区间,用 map
维护前缀异或和的种类即可
设哈希值的值域为 \(V\),期望正确概率 \(P\) 约为 \(\left(1-\dfrac 1V\right)^{n^2}\),取 \(V=2^{64},n=3\times 10^5\),此时 \(P\approx1-10^{-8}\)
时间复杂度 \(\mathcal O(n\log n)\)
Z. [IOI 2018] 组合动作
考虑逐步确定 \(S\) 的前缀 \(S'\),首先可以通过两次询问(先询问 \(\txt{ab}\) 然后询问 \(\txt{a}\) 或 \(\txt{x}\))得到 \(S_1\),然后记剩下的三个字符分别为 \(\txt a,\txt b,\txt c\),那么每次询问 \(S’\txt a,S'\txt b\) 即可确定 \(S_{|S'|+1}\)
但这样的操作次数是 \(2n\) 的,考虑优化,注意到构造字符串 \(S'\txt a+S'\txt{ba}+S'\txt{bb}+S'\txt{bc}\) 即可根据返回的答案 \(Q\in\{|S'|,|S'|+1,|S'|+2\}\) 确定 \(S_{|S'|+1}\),对于 \(S_n\) 直接暴力询问即可
总次数为 \(2+(n-2)+2=n+2\),可以通过本题
时间复杂度 \(\mathcal O(n^2)\)