USACO2023

发布时间 2023-08-06 16:39:04作者: yllcm

所有题都是向这篇博客学的,orz。

*loj3934. 「USACO 2023.1 Platinum」Tractor Paths

首先可以观察到,对于节点 \(x\)\(x\) 能通过 \(k\) 步向右到达的所有区间构成一个区间,假设为 \([l_{0,x,k},r_{0,x,k}]\),同理,\(x\) 向左走 \(k\) 步到达的所有区间也是区间,设为 \([l_{1,x,k},r_{1,x,k}]\)

所以一组询问 \(x,y\) 实际上让我们求 \(\sum|[l_{0,x,k},r_{0,x,k}]\cap[l_{1,y,d-k},r_{1,y,d-k}]|\)。其中 \(d\)\(x,y\) 间最短路。

不过这个区间交实际上可以差分拆开,所以两边是独立的,暴力查询即可。

*loj3935 「USACO 2023.1 Platinum」Mana Collection

注意到答案只和每个点最终到达的时间有关,假设到达的所有节点的集合为 \(S\)\(f_u\) 表示节点 \(u\) 最后一次到达的时间与 \(s\) 的差,你需要最大化 \(s(\sum_{u\in S}m_u)-\sum_{u\in S}f_um_u\),所以假如求出每个 \(S\) 的最小的后面一部分就可以用斜率优化回答询问。

考虑一个 DP。\(f(S,pos,t)\) 表示已经经过集合 \(S\),当前点在 \(pos\)\(f_{pos}=t\),那么有 \(f(S,pos,t)+(dis(pos,nxt)+t)m_{nxt}\to f(S,pos,t+dis(pos,nxt))\)

注意 \(t\) 非常大,并且 \(t\) 是一个毫无意义的值,所以要考虑把 \(t\) 去掉。对于 DP 过程,\(t\) 只与贡献有关,我们可以拆贡献。注意到一个 \(dis(pos,nxt)\) 的贡献次数为它后面所有点的 \(m_u\) 的和,所以可以考虑倒着做 DP,找到 \(dis(pos,nxt)\) 的后缀 \(m_u\) 的和。

但是关键在于 \(t\leq s\) 的限制,这看起来有些棘手,不能通过拆贡献的方法解决。不过可以发现 \(t>s\) 的路径是不优的,这是因为在最终的路径中,一段前缀是负贡献的,把这段前缀掐掉满足终点不变且答案更大。

总复杂度 \(\mathcal{O}(2^nn^3+q)\)

*loj3936. 「USACO 2023.1 Platinum」Subtree Activation

这个题被我猜过去了,抄一下

注意到我们的任务是求出一个排列,最小化 \(sz_{p_1}+sz_{p_n}+\sum_{i<n}w(p_i,p_{i+1})\),其中 \(w(u,v)=\begin{cases}|sz_u-sz_v|&u\in sub(v)\lor v\in sub(u)\\sz_u+sz_v&\text{otherwise}\end{cases}\)

在树上构造排列的方式是:先构造子树的排列,归并,并将根插入之中。考虑插入到一个子树的排列之间的影响,假如插入到两个没有祖先关系的节点之间,对答案的贡献是 \(2(sz_u-sz_x-sz_y)\),否则是 \(2(sz_u-\max(sz_x,sz_y))\),显然后者是更优秀的。如果插入两个子树之间,对排列的贡献是 \(2(sz_u-sz_{s_1}-sz_{s_2})\),如果插入到末尾,贡献是 \(2(sz_u-sz_s)\),显然后者是更优的。

如果考虑每个点的贡献,可以发现插入一个节点之后,一棵子树内只有不超过两个点的系数会发生变化。然后讨论一下 DP 即可。

说白了其实只要考虑插入到两个没有祖先关系的节点之间的系数变化。

*loj3949. 「USACO 2023.2 Platinum」Hungry Cow

好题!

题解其实只有一句话:用线段树维护被覆盖的节点个数,被覆盖的节点的和,向右侧剩余的干草堆。合并的时候采用和楼房重建类似的合并方式。

有愚蠢的线段树分治做法,可能是这个题开 6s 的原因,但是没人愿意写。

loj3950. 「USACO 2023.2 Platinum」Problem Setting

最简单的一个题。

考虑一个 \(m\) 位二进制数,\(a_i\)\(j\) 位为 \(1\) 当且仅当它在 \(j\) 是 hard 的。条件是选出来的数构成偏序且大小升序,随便 DP 一下。需要做一个半在线的高维前缀和,方法是考虑 DP \(f_{i,j}=f_{i,j-1}+f_{i-2^j,j-1}\)。复杂度 \(\mathcal{O}(n+2^mm)\)

*loj3951. 「USACO 2023.2 Platinum」Watching Cowflix

很显然可以做到平方。

整体 DP 不太行的样子。不过可以大胆猜测:一个点选择的时间为一个后缀。 拿这个套整体二分容易做到 \(\mathcal{O}(n\log^2 n)\),但是太难写了。

如果观察答案的性质可以发现,答案是 \(\mathcal{O}(n)\) 量级的,这说明在参数为 \(k\) 的情况下联通块个数不会超过 \(\mathcal{O}\left(\dfrac{n}{k}\right)\),根号分治一下可以做到 \(\mathcal{O}(n\sqrt{n})\),但是常数太大了。

但是,如果你做一下整理,可以发现如果我们建立关键点的虚树,并把确定已经变黑的联通块缩起来,剩下的点的个数是不会超过 \(\mathcal{O}\left(\dfrac{n}{k}\right)\) 的,这是因为对于一条虚边,它的长度一定要大于 \(\dfrac{k}{2}\),否则将它贪心地缩起来一定更优。这样虚树上一条边代表至少 \(\mathcal{O}(k)\) 个点,说明总点数是 \(\mathcal{O}\left(\dfrac{n}{k}\right)\)。直接每次暴力 DP 是 \(\mathcal{O}(n\log n)\) 的。

这个缩点优化还是很有趣的。

*loj3961. 「USACO 2023 US Open Platinum」Pareidolia

首先有一个愚蠢的使用 \(9\times 9\) 矩阵的动态 DP 做法。

考虑没有修改,那么可以利用分治解决。具体地,每次计算跨过中点 \(mid\) 的所有区间的答案。考虑一个区间的答案是:

\[B([l,r])=g(l,mid,0)+g(mid+1,r,f(l,mid,0)) \]

\(\sum B([l,r])\),那么写式子:

\[\sum B([l,r])=(r-mid)\sum_lg(l,mid,0)+\sum_{l,r}g(mid+1,r,f(l,mid,0)) \]

注意到 \(f(l,mid,0)\) 值域只有 \(6\),考虑设 \(cnt(i)=\sum_{l}[f(l,mid,0)=i]\)。那么:

\[\sum_{l,r}g(mid+1,r,f(l,mid,0))=\sum_icnt(i)\sum_r g(mid+1,r,i) \]

所以线段树上维护:\(\sum_tg(t,r,0)\)\(\sum_t g(l,t,i)\)\(cnt(i)\)。讨论一下不难维护。

这类统计问题一般就是转化(分治,DP)+推式子解决。

*loj3962. 「USACO 2023 US Open Platinum」Good Bitstrings

Stern-Brocot 树好题。

考虑怎么判断 \((x,y)\) 合法,但是判断合法很麻烦,所以尝试转化一下题目给出的条件。\((x,y)\) 合法当且仅当:

  • \(x\in[1,a],y\in[1,b]\)
  • 对于 \(i\in[1,x],j\in[1,y]\),一定有 \(\dfrac{i}{x}\leq\dfrac{j}{y}\Leftrightarrow \dfrac{i}{a}\leq\dfrac{j}{b}\)

转化一下,可以发现等价于不存在 \(\dfrac{i}{j}\)\(\dfrac{a}{b}\)\(\dfrac{x}{y}\) 之间,可以使用 SBT 刻画,或者说,考虑在 SBT 上二分,如果 \(\dfrac{i}{j}\leq \dfrac{a}{b}\),那么它的左子树就没救了。同理如果 \(\dfrac{i}{j}>\dfrac{a}{b}\),那它的右子树就没救了。说明分数的取值构成 SBT 上的一条链。

但是如果不是最简分数,这个做法可能覆盖不到。所以要讨论不是最简分数的情况 \(\dfrac{ti}{tj}\)。如果链上 \(\dfrac{i}{j}>\dfrac{a}{b}\),那么 \(t=1\),否则把剩下的分数拉出来排成一个序列,那么只需要保证 \(tX_i<X_{i+1}\lor tY_i<Y_{i+1}\) 就好了。用式子刻画,并用 SBT 二分的经典优化,就可以 \(\mathcal{O}(T\log^2\max\{a,b\})\) 了。

我开始试图把非最简分数和最简分数放一起处理,没想到可以直接分类讨论掉。

*loj3963. 「USACO 2023 US Open Platinum」Triples of Cows

神秘邻域信息维护题。

先转化一下:两个点有边当且仅当它们中间的点都被删了。如果考虑重构树的话会非常麻烦,所以考虑把中间被删掉的点缩成一个白点,那么答案是长度为 \(5\) 的链的个数(只需要黑点不重复)。

这玩意看起来十分不可维护。但是如果你推个式子,假设 \(s_u\) 表示 \(u\) 的儿子个数:

  • 如果两个白点相同,那就是 \(\sum_u (s_u+1)^{\underline{3}}\)
  • 讨论哪个点是 LCA,都可以推出来式子。

所以答案可以被表示成了只和 \(s_u\) 有关的式子,整理一下发现只需要维护:

  • 黑点的二阶儿子个数。
  • 白点的一阶儿子和三阶儿子个数。

每次删点的时候更新三级父亲的信息即可。

总之这类树上问题可以只维护 \(s_u\) 的信息,这样单点更新的代价会小一些。