ABC 312
前三题氵
给定一个由 (,?,)
组成的字符串。每个 ?
可以设定为任意括号。求有几种设定方法使得整个是合法括号序列。
套路,dp
给定 \(n\) 个两两不相交的长方体,对每个长方体,求有多少个长方体与其有公共面。
有一个可以大幅度优化代码麻烦程度的小技巧:因为坐标范围很小,我们直接把每个长方体拆成 \(x*y*z\) 个小立方体看就行。
对于第 \(i\) 个长方体的每个小立方体 \((a,b,c)\),让它相邻的六个小立方体都统计一下:我的相邻小立方体有来自第 \(i\) 个长方体的。这其实就等价于有公共面。
有 \(n\) 个东西类型为 \(0,1,2\)。
类型 \(0\) 的是罐头,无限制,有一个价值。
类型 \(1\) 的也是罐头,需要开罐器,也有一个价值。
类型 \(2\) 的是开罐器,有一个可开罐数量。
只能选 \(m\) 个东西,求最大价值和。
这题比 E 氵
考虑枚举拿的开罐器数量,同时维护此时的最大价值和。
用一个 multiset 保存当前持有的罐头。初始时把最大的 \(m\) 个类型 \(0\) 加入 multiset 并令初始价值和为它们的价值和。(赛时居然把所有类型 \(0\) 的都加入 multiset 了,一定注意是最大的m个)
然后枚举拿的开罐器数量,注意开罐器一定是按照可开罐数量从大到小拿。(如果某次发现上一次的总可开罐数量已经足够开启所有罐头,就 break)
假设这次拿的开罐器可以打开 \(x\) 个罐头,接下来从上一次开罐的结尾开始,再把之后的 \(x\) 个罐头加入 multiset,同时也令当前价值和加上这 \(x\) 个罐头。
最后把 multiset 中多余的罐头去掉。(注意要考虑拿了一些开罐器)这时剩下的就是拿这么多开罐器的答案了。
每次让 \(ans\) 和维护的最大价值和取 \(\max\) 即可。
找出树上有多少个三个点的点组,使得不存在一条简单路径包含这点组内的三个点。
每一个符合要求的三点组 \((i,j,k)\),一定唯一存在一个结点 \(v\),使得 \((i\rightarrow v,j\rightarrow v),\;\,(j\rightarrow v,k\rightarrow v),\;\,(i\rightarrow v,k\rightarrow v)\) 这三对路径中,每一对路径都存在一个非 \(v\) 的结点重复。(说人话就是从点 \(v\) 往外辐射出去)
因此只需要考虑每一个点 \(v\),统计对应的 \((i,j,k)\) 个数,加起来就是答案。
而假设固定了点 \(v\),\((i,j,k)\) 的个数就是从 \(v\) 的每个儿子子树的规模中,任取三个相乘的和。(例如 \(v\) 有 \(4\) 个儿子,\(4\) 颗子树的规模分别为 \(2,1,1,3\),答案就是 \((2*1*1+2*1*3+1*1*3\))
如果 \(v\) 的子结点不足 \(3\) 个,对答案的贡献为 \(0\)。
“任取三个相乘的和” 这个问题可以用 DP 解:\(dp_{i,j}\) 表示前 \(i\) 个元素任取 \(j\) 个数相乘,求和是多少。时间复杂度 \(O(\)序列长度\()\)。
因此对于一个固定的结点 \(v\),它对答案的贡献可以以 \(O(sons[v])\) 的复杂度求出,\(sons[v]\) 是以 \(v\) 为根时 \(v\) 的子结点个数。
但是还有一个问题:以 \(v\) 为根时,各子结点的子树规模怎么求?其实做一遍换根 DP 就行。
总复杂度 \(O(n)\)。
其实这题用到的知识点并不超纲。赛时卡在了如何求出“任取三个相乘的和”上。