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\),效果是相同的。

posted @ 2025-12-03 16:56  adam01  阅读(18)  评论(0)    收藏  举报