[codechef]BSG

题面

给一个长度为 \(n\) 的括号串 \(S\),A 和 B 要在上面玩游戏。

每轮 A 先在 \(S\) 中选一个 ()子序列 删掉,然后 \(B\) 也选一个删掉,如果 A 或 B 无法选择,那么就结束,并且该轮不计入总轮数。

A 希望总轮数最多,B 希望总轮数最少,求最终会进行多少轮。

数据范围:\(n\le 2\times 10^5\)

题解

首先分析一下 B 的决策,容易发现 B 每次一定会选择最前的(和最后的)

然后考虑 A ,可是我们并不好分析 A 的策略,因为如果(选太前了,那么后面可能就没得选了,而选太后了前面的(又会被 B 选完,但我们可以发现,设最终答案为 \(ans\) ,那么 A,B 肯定会选择了前 \(2ans\)( 和后 \(2ans\))

这个时候,我们就可以考虑二分答案 \(mid\),然后把序列中前 \(2mid\)(和后 \(2mid\))扣下来组成一个新的串 \(S'\),然后再对 \(S'\) 考虑能否被 A,B取完。

这时候我们发现因为只有 \(2mid\) 对括号串,所以在 A,B 取的时候,括号串 \(S'\) 必须保持合法 ,所以对于 B 取的首尾括号必须是匹配的。

那么对于 A 来说,因为他能取的括号串是灵活的,所以我们这个时候就是想让 B 能够操作的次数最多。

所以若当前 \(S'\) 形式是 (A),那么我们就可以把当前的首尾留给 B,并且让 B 能够操作的次数 \(+1\)

否则若当前 \(S'\) 形式是 (A)(B)(C)..(D),那么这个时候就必须让 A 疯狂操作,让整个序列只剩成 (A/B/C/D)的形式。

能够取完 当且仅当 取的时候时刻保持 B 能够操作的次数 \(\ge\) A 要操作的次数。

所以就可以用搜索(应该是的),设 \(f(S)\) 表示 B 能够操作的次数 \(-\) A 要操作的次数,根据当前 \(S'\) 形式来转移。

做一次的复杂度是 \(O(n)\) ,所以整个复杂度就是 \(O(n\log n)\)

启发

  • 在不知道怎么决策的时候可以用二分!
  • 在 A 只能操作什么,B 能任意操作的时候,可以考虑记 A 能够操作的次数 和 B 要操作的次数。
posted @ 2022-07-11 19:49  qwq_123  阅读(91)  评论(0编辑  收藏  举报