2020.12.01提高组模拟总结
GMOJ 2020.12.01【NOIP提高A组】模拟
一鼓作气,四题暴力......
T1.6910 卡特兰数(catalan)
赛时发现可以将限制简化为一棵树,尝试树形 \(dp\),然后尝试合并子树尝试的一早上......
正解区间 \(dp\),设 \(dp[l][r]\) 表示区间 \([l, r]\) 的合法出栈序列数,每次枚举最晚出栈的数 \(k\),转移显然 转移 \(dp[l][r] = \sum {dp[l][k - 1] · dp[k + 1][r]}\),但是我们需要考虑限制:
- 首先不能有 \((k, i), \ l \leq i \leq r \ \& \ i \neq k\),(强调限制 \((f, g)\) 表示 \(f\) 不能在 \(g\) 之后出栈)
- 同时可知对于 \(i, \ l\leq i < k\),\(i\) 都在 \(k\) 入栈前出栈,而对于 \(j, \ k < j \leq r\),\(j\) 都在 \(k\) 入栈后入栈
(这不显然吗),所以 \(j\) 势必会在 \(i\) 之后出栈,言下之意呢,就是不能有 \((j, i)\) 的限制
\(O(m)\) 判断的话总时间复杂度达到 \(O(n^3 m)\),想必不能通过此题,但可以发现以上需要判断的限制 \((f, g)\) 中,\((f, g)\) 都是连续的,形象地说:
- 若我们将每个限制 \((f, g)\) 当作二维平面上的一个点,
- 那么对于第一类限制,实质上是查询矩形 \((k, l, k, k - 1)\) 和 \((k, k + 1, k, r)\) 中是否有点(矩形 \((x1, y1, x2, y2)\) 表示矩形地左上角为 \((x1, y1)\),右下角为 \((x2, y2)\))
- 对于第二类限制,就是查询矩形 \((k + 1, l, r, k - 1)\) 中是否有点
那么二位前缀和优化判断即可,时间复杂度 \(O(n^3 + n^2)\)
T2. 6911 莫队(team)
令 \(pre_i\) 表示 \(i\) 之前第一个与 \(a_i\) 相同的位置,那么合法的左端点应满足 \(l \geq \max_{i = l}^r{pre_i}\)。
那么区间 \([L, R]\) 的答案就可以表示为:
显然 \(\max_{i = L}^{r}{pre_i}\) 是递增的,所以我们可以用线段树维护前缀 \(\max\)。
考虑线段树需要支持什么操作:1. 修改一个数;2. 查询区间 \([L, R]\) 的答案(前缀 \(\max\) 的和)
如何维护呢?对于线段树上每个节点 \(t\),令 \(ls_t, \ rs_t\) 表示它的左右儿子,同时维护 \(ma_t\) 表示区间 \(t\) 的 \(pre\) 的最大值,\(f_t\) 表示区间 \(t\) 在区间 \(fa_t\) 上的 前缀最大值之和,在区间 \(fa_t\) 上的意思是 以 \(t\) 的父亲的区间的左端起始的前缀最大值(根节点的话就是它本身)。
设当前线段树上更新到节点 \(t\),\(ma_t\) 很好维护,而 \(f_t\) 需要用到 \(fa_t\) 的信息,所以我们 在回溯到 \(fa_t\) 时再更新 \(f_t\)。言下之意呢,就是说此时我们需要更新 \(f_{rs_t}\) (区间 \(ls_t\) 与 \(t\) 的左端相同,不需要更新),那么我们将 \(ma_{ls_t}\) (以下表述为 \(ma'\)) 代入区间 \(rs_t\),设更新到 \(u\):
- 若 \(ma' \leq ma_{ls_u}\),也就是说 \(ma'\) 无法影响区间 \(rs_u\) 的前缀最大值,那么继续更新 \(ls_t\) 返回时加上 \(f_{rs_u}\)
- 若 \(ma' > ma_{ls_u}\),也就是说区间 \(ls_u\) 的前缀最大值会被全部改变为 \(ma'\),于是继续更新 \(rs_t\),返回时加上 \(ma'(mid - l + 1)\)
- 当 \(l = r\) 时,显然直接返回 \(\max(ma', ma_u)\)
这样子我们就维护好啦!至于询问,其实和维护 \(f_t\) 的过程十分类似,我们只需要代入 \(L - 1\),每次先询问左区间,然后将左区间的 \(ma\) 和 \(L - 1\) 取个 \(\max\) 再代入右区间即可。
T3. 6912 数论(math)
\(Solution\)
T4. 6913 异或(xor)
构造题会打不会证在此就不赘述了