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 题解的主要内容,如果未能解决你的问题,请参考以下文章