题意:给一个合法括号序列,然后现在每次把一个位置上的括号反转,问反转另一个位置使得括号序列重新变得合法的最小位置是哪里。
思路:首先我们要分两种情况考虑。
- 我们反转的是
(
。
那么聪明的读者一定会发现我们只需要把第一个)
给反转就好了。
原因就是因为我们原来想要给打开括号数量\(+1\),而现在变成了\(-1\),所以后面的肯定会有一个\(-1\)的打开括号数量,于是我们必须把前面的一个补上去,越早越好。
- 我们反转的是
)
。
这就比较麻烦了。首先我们果断二分。
那么考虑一下我们如果要反转第\(i\)位,需要满足什么条件。
首先我们这次的括号序列不合法是因为多了\(2\)个打开的左括号。
那么我们现在从(
改一个为)
的目的是要让这个\(2\)消下去。
并且还要满足每时每刻的打开括号数量都\(\ge 0\)。
所以我们就需要一个线段树来维护每一位上的打开的括号数量,然后保证从\(i\)到\(n\)的每一位上的打开括号数量都\(\ge 2\)即可。因为我们现在是把(
改成)
,减少了两个打开的括号数量。
我在写的时候只是维护了每一位上是(
(\(1\))还是)
(\(-1\)),于是十分不爽地发现要维护最小前缀和,很悲伤地在线段树中维护了个结构体,就显得代码比较丑。
需要注意的是如果这样写我们只能判断\(\text{sum}(1,i-1)+\min(i,n)\ge 2\)了。复杂度\(\times 2\)。跑得贼慢。
需要注意我们这样二分出的\(i\)是否真的是个(
。(如果我们费尽心机竟然把一个)
该回去了就不太好了)
假如我们第一个成功的地方是一个)
,那么我们上一个位置的时候肯定可以满足(因为当前这位会使所有的和更小。
那么矛盾,证毕。
只是注意下二分的时候找的是最前的那个就好了。