CSP2019 题解

Posted Lonely_233

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSP2019 题解相关的知识,希望对你有一定的参考价值。

D1T1

显然把所有排列列出来,不难发现答案的第 \\(i\\) 位只与 \\(k\\) 二进制拆分后的 \\(i\\) 位是 0/1 和 \\(i-1\\) 位是 0/1 有关。

那么把 \\(k\\) 分解,记分解后第 \\(i\\) 位为 \\(a_i\\),那么答案第 \\(i\\) 位为 a[i-1]?!a[i]:a[i]

D1T2

先考虑链如何做,是个经典问题,记 \\(f_u\\) 表示 \\(1~u\\) 中的新增的匹配数量。

显然 \\(f_u\\) 可以从上一次匹配的左括号位置转移,求答案就记个前缀和就好了。

考虑如何扩展到树上,记 \\(f_u\\) 表示根到 \\(u\\) 这条路径上新增的匹配数量,\\(dp_u\\) 表示根到 \\(u\\) 的匹配数量。

那么 \\(dp_u=dp_{fa_u}+f_u\\)

我们维护一个栈,每次搜到一个左括号就把他压到栈里,\\(f_u=0\\)

当搜到右括号时,如果栈是空的,那么 \\(f_u=0\\)

否则,\\(f_u=f_{fa_{stk_{tp}}}+1\\),这个转移的意思就是到 \\(u\\) 的新增匹配,要么是由栈顶父亲那里的匹配加上 \\([stk_{tp},u]\\) 这一对括号构成的,要么是 \\([stk_{tp},u]\\) 这对括号。

注意到回溯的时候栈里存的可能不是 \\([1,u]\\) 里已经匹配的,那么我们每次退栈的时候记录退栈的元素,搜完子树后再入栈。

代码

D1T3

D2T1

D2T2

D2T3

首先不难发现一个 dp :记 \\(dp_{i,j}\\) 表示划分了 \\(i\\) 个数,上一次划分位置是 \\(j\\) 的最小值。

记个前缀和转移,\\(dp_{i,j}=\\displaystyle \\min_{sum_i-sum_k \\leq sum_j-sum_i} \\{dp_{k,i}+(sum_j-sum_i)^2\\}\\),拿到 36 分。

考虑优化,固定 \\(i\\),发现 \\(j\\) 变化的时候, \\(k\\) 也在随着变化。

那么维护一下 \\(dp_{k,i}\\) 的最小值就好了,拿到 64 分。

继续优化,考虑这么一个式子 \\((a+b)^2 \\geq a^2+b^2\\)

从这个式子我们得知尽量多分几段可以使答案更小。

所以我们每次只要找到第一个能转移的 \\(k\\) 进行转移就行了,记转移点为 \\(f_i\\)

那么我们要求的就是最大的 \\(k\\) 使得 \\(sum_i-sum_k \\geq sum_k-sum_{f_k}\\)

移项一下,得到 \\(sum_i \\geq 2 \\times sum_k-sum_{f_k}\\)

可以通过暴力打出决策点,发现 \\(f_i\\) 是单调的,即假如有 \\(t<f_i\\),那么 \\(t\\) 绝对不是 \\(f_{i+1}\\)

所以这个用单调队列维护一下即可。

不想写高精度所以用了 __int128。

代码

D2T3

以上是关于CSP2019 题解的主要内容,如果未能解决你的问题,请参考以下文章

CSP-S 2019 题解 游记

CSP2019题解

CSP2019 题解

题解[CSP-S2019] Emiya 家今天的饭

CSP2019 树上的数 题解

csp2019 Emiya家今天的饭题解