NOIP2025题解
NOIP 2025
A. candy
答案一定是选择一些 \(x+y\),然后选择一些编号不同的 \(x\)。
所以贪心选择 \(x\),按 \(x\) 排序,选择一段前缀。
\(x+y\) 的选法就是找到最小的一直选。
按 \(x\) 排序,设 \(v=\min x_i+y_i,pre_i=\sum_{j\leq i}x_j\):
答案就是 \(\max_{i\in[0,n],pre_i\leq m} pre_i+2\lfloor\frac{m-pre_i}{v}\rfloor\)。
B. sale
令 \(b_iw_i=a_i\)。
考虑情况不合法当且仅当:
找到三个位置 \(i,j,k\) 使得 \(a_i>a_j+a_k\),且 \(2a_j>a_i(2a_k<a_i)\)。
此时 \(a_i>a_j>a_k\)。不妨先把 \(a\) 从小到大排序。此时 \(i>j>k\)。
此时如果 \(w_i=2,w_j=w_k=1\),且按 \(b\) 排序后 \(b_j\) 和 \(b_i\) 之间都是 \(w=2\),\(b_i\) 和 \(b_k\) 之间 \(w=2\)。
并且 \(a\geq a_i\) 的 \(w\) 之和(不包括 \(w_i\))是 \(m-1\)。
那么贪心策略会选择 \(a_j+a_k\),但是最优做法是选择 \(a_i\)。
考虑对上面的情况计数。
“排序后”这个条件太麻烦了。考虑排序前要求哪些位置 \(w=2\)。
观察一下,发现对于 \(u\in (k,j)\),都要求 \(w_u=2\),否则不合法。
对于 \(u\in (j,n]\setminus \{i\}\) 的,分成两部分 \((j,i)(i,n]\),第一部分 \(w=1\) 才会被选中,第二部分一定会被选中。
于是问题就变成,第一部分一开始 \(w\) 没有贡献,第二部分一开始 \(w=1\),两部分每个位置都可以贡献 \(+1\),问总贡献 \(m-2\) 的方案数。
左侧大小 \(i-j-1\),右侧 \(n-i\),于是方案数就是 \(\binom{n-j-1}{m-2-(n-i)}\)。
然后对于 \(u\in[1,k)\),\(w\) 随便。方案数 \(2^{k-1}\)。
于是答案就是 \(\sum_{i\geq 1}\sum_{j\geq 1}\left(\binom{n-j-1}{m-2-(n-i)}\sum_{k\geq 0} 2^{\max(0,k-1)}[a_j+a_k<a_i,2a_j>a_i]\right)\)。
\(\sum_k\) 可以直接变成 \(2^{\sum_{k\geq 1}[a_j+a_k<a_i]}\)。
所以就是 \(\sum_{i\geq 1}\sum_{j\geq 1,2a_j>a_i}\left(\binom{n-j-1}{m-2-(n-i)}2^{\sum_{k\geq 1}[a_j+a_k<a_i]}\right)\)。
对于 \(k\),合法的是一段前缀。且随着 \(j\) 单调。所以直接暴力移动找,均摊线性。
复杂度 \(\mathcal{O}(n^2)\)。
C. tree
很厉害。
考虑 \(u\) 被子树内的点贡献,是一个比较常见的暴力。
通过延迟决策,设计 dp \(f(i,j,k)\) 表示 \(i\) 的 \(\text{mex}=j\),子树内有 \(k\) 个点还没有决策的最优答案。
因为 \(j\leq sz_i\),转移复杂度也不超过背包,所以按照树上背包的复杂度分析,是不超过 \(\mathcal{O}(n^3)\) 的。
但是很可惜这个暴力不太好优化。
但是这个 dp 思路是可以给我们启发的:考虑 dp 的转移过程,发现 \(j\) 只和子树的 \(\max j\),以及消耗了多少 \(k\) 有关系。
也就是我们可以得到树的一个链剖分:把子树的 \(\max j\) 作为重儿子。有什么用呢。
换一种方式思考:
考虑反过来贡献,考虑一个点会对祖先造成什么贡献。
发现一个点会对祖先的一条链造成贡献。
继续思考这个特殊性质。结合上面的暴力做法,我们发现,这种东西相当于对树进行上述链剖分,然后一个点 \(u\) 的贡献就是从某个点 \(v\in anc(u)\) 到这个点的链顶 \(top_v\),对应 \(k\) 在 \(v\) 处的消耗。
所以 \(u\) 需要找某个祖先 \(i\),然后贡献到链顶 \(top_i\)。贡献是 \(dep(i)-dep(top_i)+1\)。
上面一堆都是为了推出这个性质:即 \(u\) 的贡献是 \(t_u=\max_{i\in anc(u)}dep(i)-dep(top_i)+1\)。
I.
然后根据这个,我们可以设计出一个 \(O(nm^2)\) 的 dp:\(f(i,j,k)\) 表示 dp 到 \(i\),钦定 \(t_i=j,dep(i)-dep(top_i)+1=k\)。
转移的时候,枚举重儿子 \(u\),有 \(f(i,j,k)=j+\max_{u\in son(i)}f(u,\max(j,k+1),k+1)+\sum_{v\neq u\in son(i)}f(v,j,1)\)。
考虑对这个 dp 进一步优化。
令 \(dis_i\) 为 \(i\) 子树的高度。
我们发现,如果 \(j-k>dis_i\),那么对于子树内的任意一点,都有 \(k<j\),那么都不如贡献到 \(j\),所以 \(k\) 更大和 \(k=j+dis_i\) 是等价的。故 \(k\leq j+dis_i\)。
为了方便转移,我们不妨令 \(k'=j-k\leq dis_i\)。设新状态为 \(f'(i,j,k')\)。
于是转移变成:
- \(k'=0\):\(f'(i,j,k')=j+\max_{u\in son(i)}f'(u,j+1,0)+\sum_{v\neq u\in son(i)}f'(v,j,1)\)
- \(k'\neq 0\):\(f'(i,j,k')=j+\max_{u\in son(i)}f'(u,j,k'-1)+\sum_{v\neq u\in son(i)}f'(v,j,1)\)
注意到 \(k'\leq dis_i\)。且转移(绝大部分)跟高度有关,这让我们想到了长剖优化 dp。
于是直接上套路。转移有点小麻烦。复杂度 \(\mathcal{O}(nm)\)。
II.
根据性质的另一种做法。
注意到对于 \(k<j\) 的部分,贡献都是 \(j\),所以我们考虑直接跳过 \(k<j\) 的中间状态,直接转移整条链。
对于 \(i\),重链的状态不超过 \(sz_i\) 种。注意到统计到的点对数量其实是 \(\sum_{i\in leaf} dep_i=\mathcal{O}(nm)\) 的,所以只要能 \(\mathcal{O}(\log)\) 之内转移就行了。
考虑设计 dp 状态。
\(f(i,j)\) 表示,\(t_i=dep(i)-dep(top_i)+1=j\) 的子树答案。
然后没法直接转移,问题是轻儿子的信息不足。
于是 \(g(i,j)\) 表示 \(i\) 为重链顶,\(t_i=j\) 的子树答案。
分别对应 I. 中的 \(f(i,j,j)\) 和 \(f(i,j,1)\)。相当于把 \(k=j\to 1\) 中间的步骤直接跳过了。
\(f\) 的转移比较简单,要么是轻儿子贡献为 \(g(u,0)\),要么是重儿子 \(f(v,j+1)\)。
也就是 \(f(i,j)=\sum_{u\in son(i)}g(u,0)+\max_{v\in son(i)} f(v,j+1)-g(v,0)\)。
然后 \(g\) 转移,考虑把重链分成 \(dep-dep_i+1\leq j\) 和 \(>j\) 两部分。
就是枚举 \(dep_u-dep_i=j\):
\(g(i,j)=j^2+\max_{u\in tr(i),dep_u-dep_i=j}\left(f(u,j+1)+\sum_{fa_k\in path(i,fa_u)}g(k,j)\right)\)。
其中 \(j^2\) 就是 \(dep-dep_i+1\leq j\) 里面每个点 \(j\) 的贡献。
如果不存在就是 \(g(i,j)=j+\sum_{u\in son(i)}g(u,j)\)。
然后后面那个 \(\sum_k\) 使用数据结构,把 \(g(k,j)\) 贡献到其所有兄弟的子树内。做子树加,然后查询就是单点查询。可以使用树状数组维护。
复杂度 \(\mathcal{O}(nm\log n)\)。
D. query
不会数据结构啊。
I.
考虑把区间看做点 \(l_i,r_i\) 放到二维平面上。
问题是给出 \(L_j,R_j\),求 \(\max_{1\le l\le i\le r\le n}\{\sum_{i=l}^{r} a_i\mid L_j\le r-l+1\le R_j\}\)。
在二维平面上,我们发现,要求的其实是 \(l\leq i\),且在 \(r=l+L\) 和 \(r=l+R\) 两条直线之间的点的最大值。
这是一个梯形。并且可以拆成平行四边形和一个等腰直角三角形。
对于平行四边形,我们知道对于已知的 \(l\),要求的是 \(r\in [l+L,l+R]\) 内点的最大值。使用 ST 表加上单调队列可以对每个 \(i\) 都算出来。
对于三角形,不太好直接算,于是拆成两个平行四边形(做法相同),以及一个对应直角的正方形。
正方形就是 \(l\in [i-d,i],r\in [i,i+d]\) 内 \((l,r)\) 的最大值,两侧分别求,然后并起来就好了。
II.
考虑 \(L=R\) 的特殊性质。
我们发现,使用单调队列即可。
考虑 \(L\neq R\) 会漏掉那些情况。
我们发现对于 \(i\) 加入后,会被其后继 \(nx_i\) 弹出队列。此时 \([i,nx_i)\) 这部分元素,可能还可以被某些 \([i,r]\) 贡献。
具体的,当 \(r=nx_i+i-1\) 时,将 \(i\) 弹出。在 \(r=i+R-1\) 后,变为不合法。
于是贡献就是 \(\max_{i\in [nx_i+i-1,i+R-1]}pre_i\)。
然后问题变成要对两组区间取 \(\max\):
- 一组互相不包含的区间,也就是贪心用单调队列得到的结果。
- 一些 \([i,nx_i)\)。这种东西发现除包含外不交。刻画包含关系的就是笛卡尔树。所以在树上 dfs 把标记下传就可以了。
III.
考虑特殊性质 \(L>n/2\)。
此时所有区间会经过中点。进一步拓展,对于长度 \(\in [d,2d)\) 来说,至少会经过一个间隔为 \(d\) 的点,最多两个。
当然,有丰富数据结构经验的应该可以直接跳过所有特殊性质,意识到可以通过撒关键点来做。
然后发现 \([d,2d)\) 可以通过值域倍增分块预处理来解决。
也就是预处理 \([2^i,2^{i+1})\),然后两侧的散块通过关键点,讨论是位于被点分割的区间的哪一部分进行计算。
还有一种做法就是,先离散化,然后如果相邻两个位置 \(2b_i<b_{i+1}\) 则插入 \(2b_i\),效果是相同的。

浙公网安备 33010602011771号