ZR 2025 十一集训 Day 4

无论春夏 无论秋冬
无论多少岁月将我们分隔

——洛天依《所以我戴上了耳机》


CF1606E

思维难度:\(\color{#52C41A} 绿\) *1700

如何设计状态?

首先第一维一定是剩余 \(i\) 个人,这个是毫无疑问的。

然后看我们实际上关心的是什么。因为要算没有人胜利的方案数,而如果有人胜利,那么这个人一定是初始状态下所有人中血量最大的,且在后面的过程中也能一直保持最大。所以不妨把当前局面的最大血量丢到状态里,令 \(f_{i,j}\) 为剩余 \(i\) 个人,其中最大血量为 \(j\),最终没有胜者的方案数。

发现这是正确的,转移只需要考虑血量最大的人是否存活到下一轮即可。

submission

天依宝宝可爱!


CF1716C

思维难度:\(\color{#F39C11} 橙\) *1000

大水题,注意到答案的形态就做完了。

但是被直接走直线的情况硬控 2h,甚至没有想到可以对于直接走直线直接暴力一遍(后来想到了才过了),糖糖糖糖糖。

submission

天依宝宝可爱!


CF1716D

思维难度:\(\color{#F39C11} 橙\) *1100

诈骗题,注意到最多操作 \(O(\sqrt n)\) 次就做完了。

submission

天依宝宝可爱!


洛谷 P3574

思维难度:\(\color{#FFC116} 黄\) *1300

比较简单,显然是树形 dp,重点在于确定子树顺序。不过写个子树个数多的 dp 方程就可以找到规律了。

例如三个子树:

\[f_u = \max(1 + \max(f_i , sz_i+1) , 1 + 2 + sz_i + \max(f_j , sz_j+1) , 1 + 2 + 2 + sz_i + sz_j + \max(f_k , sz_k+1)) \]

前两项需要满足:

\[\max(1 + \max(f_i , sz_i+1) , 1 + 2 + sz_i + \max(f_j , sz_j+1)) < \max(1 + \max(f_j , sz_j+1) , 1 + 2 + sz_j + \max(f_i , sz_i+1)) \]

可以发现后面所有相邻两项,把包含的 \(sz_i + 2\) 都减掉之后和上式是一样的,直接按照这个排序即可。

submission

天依宝宝可爱!


CF1748E

思维难度:\(\color{#F39C11} 橙\) *1100

注意到要求就是笛卡尔树相同就做完了。

分享一个给定 \(n \times m \le 10^6\) 但不具体规定 \(n,m\) 的开数组技巧,不需要用到 vector。

开一个结构体,里面存一个 \(10^6\) 的数组,然后重载 [] 运算符即可,代码:

struct
{
	int v[M];
	il int* operator[](int i){return v+i*(m+1);}
	il const int* operator[](int i)const{return v+i*(m+1);}
} ;

submission

天依宝宝可爱!


CF1830D

思维难度:\(\color{#52C41A} 绿\) *1900

挺 Ad-hoc 的一个题。反正我不会。

有一个显然的错误的贪心,就是黑白染色,但是很容易 hack,随便搞一个有几个点有很多个儿子的树就可以了。

那这时候该怎样是最优的呢?可以在黑白染色的基础上,舍弃一些点(存在一些相邻点颜色相同),尽量把那一堆儿子都染成 \(0\) 会更优。

显然可以考虑 dp。设计一个类似于「\(f_{u,0/1}\) 为子树 \(u\) 根结点染成颜色 \(0/1\) 的最大价值」的东西。

然后观察什么会影响答案,会以什么方式影响答案。发现答案其实就是全部路径的 \(\rm mex\) 均为 \(2\) 的答案 减去 实际上 \(\ne 2\) 的答案;且 \({\rm mex} \ne 2\) 只需要考虑每个同色连通块的贡献(因为跨连通块的路径上就一定会出现 \(2\) 种颜色了)。一个大小为 \(k\) 的同色连通块的贡献为 \(\frac {k(k+1) \times c} 2\),其中当颜色为 \(0\) 时,\(c=1\);颜色为 \(1\) 时,\(c=2\)

那么就要设计 dp 使得所有同色连通块的贡献最小。

于是可以令 \(f_{u,i,0/1}\) 为子树 \(u\)\(u\) 所在的同色连通块大小为 \(i\)、颜色为 \(0/1\) 的最小贡献。背包地转移。

但是这样看起来是 \(O(n^2)\) 的呀!

先考虑优化转移,发现不能,毕竟背包这个东西除了 bitset 之外好像就没什么优化的地方了。

再考虑是否有大量没用的状态,发现如果连通块过大,一定不会很优秀。再回到初始的黑白染色——这个方案虽然不是最优但已经很优秀了,算一下发现会产生 \(< 2n\) 的贡献;那么一个大小为 \(i\) 的连通块贡献 \(\frac {i(i+1) \times c} 2\) 就需要 \(<2n\) 才可能有用,所以 \(i\) 只需要开到 \(O(\sqrt n)\) 级别就可以覆盖所有有用的状态了。

所以时间复杂度是 \(O(n \sqrt n)\) 的。

但是还有一个问题,就是空间复杂度,可以发现也是 \(O(n \sqrt n)\) 的,不能直接开。

所以考虑动态开,过程中只保留有用的部分。在 dfs 过程中,只保留在 \(u\) 到根结点的路径上的 dp 值,但是还是容易被卡到 \(O(n \sqrt n)\),构造一条链就可以。

继续观察,发现我们没必要在一开始就把 \(u\) 的空间开满,可以在遍历子树 \(v\) 后背包合并的时候,先释放 \(v\) 的空间,再把 \(u\) 的空间开到对应的大小(大小增加 \(sz_v\)),这样就相当于所用空间不变了,那么空间的开销就只在 dp 的初始化上(每个 \(u\) 都要初始化 \(f_{u,1,0/1} = 1/2\)),所以空间就是 \(O(n)\) 的了。

submission

天依宝宝可爱!

posted @ 2025-10-04 14:35  little__bug  阅读(4)  评论(0)    收藏  举报