CSP2019题解
CSP2019题解
格雷码
按照生成的规则模拟一下即可。
括号树
看到括号匹配首先想到用栈,然后又在树上就可以想到可追溯化栈。
令\(a_i=1\)表示\(i\)号节点上的括号为(
,否则为)
,
记栈为\(stk\),其中元素个数为\(top\)。
设\(f_i\)表示加上节点\(i\)所对应的括号所增加的贡献,\(g_i\)表示这个点的答案,转移很显然:
然后就没了。
树上的数
Emiya 家今天的饭
因为主要食材最大值只会有一个,钦定最大值是哪一个,又因为每一种烹饪手法最多选一次,设\(f[i][j][k]\)表示目前在第\(i\)中烹饪手法,现在做了\(j\)道菜,最多的食材用了\(k\)次,转移很显然就不写了,那么最后你把不满足要求的减掉就行了,这样子是\(O(n^3m)\)的。
考虑优化这个状态,设\(f[i][j]\)为目前在第\(i\)中烹饪手法最大值与其他的的差为\(j\)的方案数,和前面一样容斥就优化成了\(O(n^2m)\)的了。
划分
有一个比较显然但是并不会证的结论就是令最后一段的和最小。
记数列前缀和为\(s_i\),
设\(f_i\)表示\([1...i]\)最后一段最小时,最后一段为\([f_i,i]\),那么有转移
然后因为\(s\)单调,把这个式子化一下就是\(2s_j-s_{f_j}\leq s_i\),注意到一个单调队列优化\(dp\)的形式所以直接用单调队列优化dp即可。
因为要高精度,所以只能用\(f\)数组往前推求答案。
树的重心
注意一棵树的重心肯定是在其根节点所在重链上的,那么你每次断边时找到最深的满足条件的点\(x\),因为如果重心有两个的话肯定是父子关系,所以再判断一下\(fa_x\)是不是满足条件即可,这样子的话复杂度\(O(n^2)\)。
考虑优化这个东西,在重链上构造一个倍增数组跳重链,然后每次像普通倍增一样即可,然后需要换根,复杂度\(O(n\log n)\),细节见代码。