加载中...

3.17——edu166D

edu166 D

限时每日一题day15。第二次自己做出 2000 分的题目。比上次用时更少了,并且感觉这题根本没有2000分。。。

求能取反的区间数量,使得原合法的括号序列经翻转后仍是一个合法括号序列。

不难发现区间内左右括号的数量一定相等。可以将左括号看作1,右括号看作-1。对该数组作前缀和,得到 \(pre\) 数组。

这样左右括号数量相等的区间 \([l, r]\) 等价于 \(pre[l-1] == pre[r]\)。可以考虑枚举右端点,累计合法左端点的数量。

对某个点 \(r\),其作为区间右端点时,左端点 \(l\) 应满足 \(pre[l-1]==pre[r]\)。可以为每个 \(pre[i]\) 开一个存放位置的 \(vector\),这样可快速得到 \(r\) 的对应位置。

进一步想可以发现,\(l\) 的合法性也是单调的。因为在右端点固定的情况下,\(l\) 越偏左,越容易不合法(判断不合法性的依据是出现了某个 \(pre[i] < 0\)。这个比较显然,就不证明了)。因此可以二分左端点。难点在于如何弄 \(check\) 函数。

对于翻转区间 \([l,r]\),首先一定不会影响 \(i < l\)\(pre[i]\);其次也不会影响 \(i > r\)\(pre[i]\);因此只需要考虑 \(pre[l到r]\) 会不会因翻转而 \(<0\)

翻转后的改变为:对于所有 \(i \in [l,r]\)\(pre[i] - pre[l - 1]\) 均会变号。而若要保证 \(pre[l到r]\)\(>=0\),需要有:

\[-min(pre[i] - pre[l - 1]) <= pre[l - 1] \]

所以 \([l, r]\) 翻转后需满足:

\[max(pre[i] - pre[l - 1]) <= pre[l - 1] \]

\(pre[l-1]\) 为定值,提出来:

\[max(pre[i]) <= 2 \times pre[l - 1] \]

线段树维护 \(pre\) 区间最大值即可。这样做到了 \(check\) 复杂度 \(O(logn)\),总复杂度 \(O(nlog^{2}n)\)

code

posted @ 2025-03-17 16:00  jxs123  阅读(6)  评论(0)    收藏  举报