除了 L 神 txdy 我还能说啥呢。(L 神把这题搬模拟赛了。。。)

即把每个 x 换成 (),问是否能通过不多于一次区间反转(() 交换)后合法。

考虑怎样的括号串是合法的。

假设左括号为 \(a_p=0\),右括号为 \(a_p=1\),标号 \(0\sim n-1\)。

我们设 \(S_r=\sum_{k<r}(-1)^{a_k}\),则一个串合法当且仅当

\[S_p\ge0\land S_n=0
\]

容易发现只要 \(\{S_k\}\) 不同则不同,我们构造了一个 \(S\) 和括号串的双射。(折线法!)

现在再考虑反转操作。

假设反转 \([l,r)\)。

\[S_p\ge0\quad(p\le l)
\]
\[S_l-(S_p-S_l)\ge0\quad(l<p\le r)
\]
\[S_l-(S_r-S_l)+(S_p-S_r)\ge0\quad(r<p)
\]
\[S_l-(S_r-S_l)+(S_n-S_r)=0
\]

化简代换一下,也即

\[S_p\ge0\quad(p\le l)
\]
\[S_p\le2S_l\quad(l<p\le r)
\]
\[S_p\ge S_n\quad(r<p<n)
\]
\[S_n=2(S_r-S_l)
\]

考虑到直接 dp 可能会计重(合法的 \(l,r\) 不唯一),考虑如何避免计重。

一般来说,避免计重可以通过对条件的贪心化实现,也即对每种方案确定某种最优的 \((l,r)\) 对。

假设 \(l\sim r\) 间最大 \(S\) 为 \(S_{\max}\),容易发现 \(S_{\max}\le2S_l\)。

考虑对 \(S_n\) 分类讨论。

当 \(S_n>0\) 时,假设存在 \(S_p<0\),取 \(S_l=\lceil S_{\max}/2\rceil\) 总是不妨最优(顺带一提,\(2\le S_n\le S_r=S_l+S_n/2\le S_{\max}\le2S_l\));也即 \(2S_l-1\le S_{\max}\le2S_l\)。并且总是取最后一个可能的 \(l\),因此下次枚举到一个 \(S_p=S_l\) 时要查看 \(S_l\sim S_p\) 区间内有无 \(S<0\),倘没有则总是不得转移。可以证明这样的 \(l\) 总是最优且唯一。

区间合法遇到 \(r\) 时,我们总应使区间内最大数在 \(2S_l-1\sim2S_l\) 间,且存在 \(S_p<0\)。

由于可能会有另一个合法的 \(S_{r'}=S_r\) 在当前 \(S_r\) 后,考虑如何避免:考虑强制令到下一次出现 \(S_{r'}=S_r\) 之前有某个 \(S_p=2S_l+1\),或一直到 \(S_n\) 均无另一个 \(S_{r'}=S_r\) 则可行,否则不可行。容易发现不会漏统计情况,也不会计重。

第二类情况的计算可以考虑倒推,记录当前 \(S_r-S_n\) 和目前最大 \(S_r-S_n\),可以 \(O(n^3)\) 预处理。

对于第一类情况,即考虑枚举下次出现 \(S_p=2S_l+1\) 的时间来计算方案数,这个可以倒推预处理。通过预处理从 \(n\) 到 \(p\),保持 \(S_p-S_n\ge0\),当前 \(S_p-S_n\) 为某值的方案数,以及进一步到 \(S_v-S_n\),其间所有 \(S_l-S_n<S_k-S_n<S_p-S_n\),直至开头为某数的方案数,来暴力计算。这是 \(O(n^4)\) 的,并且很难优化。

考虑到这么做复杂度不优,我们略做修改,不枚举 \(r\),而是对区间内最大值容斥,枚举何时出现超过最大值边界的元素,这样此前所有可能的 \(S_r\) 均可以出现,从而无需对 \(r\) 端点去重。特别地,如果到终点均未出现超过边界的元素,这类贡献我们还是用先前第二类预处理的方式计算。

这样会好写一点,并且避免了复杂度不优的问题。

对于 \(S_p\ge0\) 恒成立的情况,我们考虑另写一个 dp 判断。

类似于刚刚的 dp,但是区间内不能出现与 \(S_l\) 相等的数。

考虑设 \(x\) 为最大的满足 \(S_x-S_n<0\) 的数,则取 \(r\) 为最大的满足 \(S_r-S_n=\min\{S_k-S_n|x<k\le n\}\) 即可。

只用计算这样的合法方案数即可,与上面过程是类似的。

只用找一个 \(l\) 满足 \(S_l=S_r-S_n/2\),且 \(S_{\max}\le2S_l\) 即可。显然这样的 \(l\) 越大越好,因此区间内不能有和目前 \(S_l\) 一样大的数,也即所有数均大于 \(S_l\)。

容易发现把前面的 dp 过程中未出现负数的方案也用来计算答案即可。

但是这样会算重,所以观察性质,容易发现某些情况的充要条件是 \(\max\{S_k|x<k\le n\}\ge2S_n\),然后就完了。

这样我们就讨论完了 \(S_n>0\) 的情况。

而 \(S_n<0\) 和 \(S_n>0\) 就差一个全局翻转,翻过来一样做即可。

考虑 \(S_n=0\),这个的合法条件是什么?

如果 \(S_p\ge0\) 恒成立,显然总可行。

否则,我们设 \(x\) 是第一个 \(S_x<0\),\(y\) 是最后一个 \(S_y<0\),则合法等价于

\[\max\{S_k|x\le k\le y\}\le2\min\{\max\{S_k|k<x\},\max\{S_k|k>y\}\}
\]

于是同样 dp 即可。

总复杂度容易做到 \(O(n^3)\)。

重新理一遍。

先考虑 \(S_n>0\) 的情况的答案。

由于刚刚的过程过于抽象,我们用 dp 方程来描述这一做法。

对于 \(\texttt x\),我们认为其 \(a_p\) 在过程中既可以为 \(0\),也可以为 \(1\),相当于是做两轮转移。

设 \(f_{m,v}\) 为已考虑前 \(m\) 项,其 \(S_p\ge0\) 均成立,且 \(S_m=v\) 的方案数。

显然有(\(\leftarrow\) 表示 dp 的贡献转移方向,不是赋值

\[f_{0,v}=[v=0]
\]
\[f_{m+1,v+1}\leftarrow[a_m=0]f_{m,v}
\]
\[f_{m+1,v-1}\leftarrow[a_m=1][v>0]f_{m,v}
\]

同样的,设 \(g_{m,v}\) 为已考虑 \(m\sim n\) 项,其 \(S_p-S_n\ge0\) 均成立,且 \(S_m-S_n=v\) 的方案数。

\[g_{n,v}=[v=0]
\]
\[g_{m+1,v+1}\leftarrow[a_m=1]g_{m,v}
\]
\[g_{m+1,v-1}\leftarrow[a_m=0][v>0]g_{m,v}
\]

我们类似地维护后缀、后缀最大值的 dp,方法类似。

假设 \(h_{m,L,v,0/1}\) 为已考虑 \(0\sim m\) 项,\(S_l=L\),\(S_m=v\),区间内是否已出现负数。

计算两遍,第一遍要求 \(v\le2L\),第二遍要求 \(v\le2L-2\)。

遇到 \(v>2L\) 或者 \(v>2L-2\) 的元素可以直接计算对答案的贡献,注意特判 \(L=1\)。

然后分类计算贡献即可。dp 不予列出。

\(S_p<0\) 同理。

\(S_p=0\) 的部分,分类左侧小还是右侧小,分别写一遍即可。

虽然但是,L 神 txdy!

代码写了 13k。。。

loj2839的更多相关文章

随机推荐

  1. USB转TTL串口 (CH340 G)

    为什么USB要转TTL串口[1]? 单片机串口基本采用TTL电平. 家用电脑很少有串口,但是有USB接口 USB的电平与TTL电平不兼容. 所以需要将USB电平转化为TTL电平. USB是什么? 接口 ...

  2. tempdb数据文件暴增分析

    背景 某客户tempdb数据文件突然暴增,导致磁盘可用空间紧张,让我们找到暴增的原因. 现象 登录到SQL专家云,通过趋势分析进行回溯,在4月12日,tempdb数据文件在3个小时内从10GB涨到了8 ...

  3. Python实现k-近邻算法案例学习

    一.介绍 你好,我是悦创. 博客首发:https://bornforthis.cn/column/Machine-learning/informal-essay/01.html 本文是由给私教学员 c ...

  4. 手撕AVL树(C++)

    阅读本文前,请确保您已经了解了二叉搜索树的相关内容(如定义.增删查改的方法以及效率等).否则,建议您先学习二叉搜索树.本文假定您对二叉搜索树有了足够的了解. 效率? 众所周知,在平衡条件下,对二叉搜索 ...

  5. Creator 2.x 升级 3.x 基础 API 差异总结

    上一篇我们介绍了 Cocos Creator 2.x 项目升级 3.x 的大流程. 但最后一步,还需要手动将之前 2.x 写的函数注释一处处的放开. 并将 2.x 的代码写法改成 3.x 的,下面我们 ...

  6. 腾讯出品小程序自动化测试框架【Minium】系列(一)环境搭建之第一个测试程序

    一.什么是Minium? minium是为小程序专门开发的自动化框架,使用minium可以进行小程序UI自动化测试. 当然,它的能力不仅仅局限于UI自动化, 比如: 使用minium来进行函数的moc ...

  7. 小H的小屋

    题解 [NOI2004]小H的小屋 前记 又鸽了好久,这回可要努力更新了 2019.6.2,痛下杀心,把电脑上所有的游戏都删掉了,提前160天奋力备考NOIP.目标:A类省队! 我是传送门 题解 这道 ...

  8. 關於scanf()的使用

    要使用scanf函數進行輸入: 1.如果用scanf()要輸入讀取基本變量的值,需要加&. 2.如果用scanf()讀取的是把字符串讀入字符數組中,則不需要加& 1 #include& ...

  9. C++Day12 虚拟继承内存布局测试

    测试一.虚继承与继承的区别 1.1 单个继承,不带虚函数 1>class B size(8): 1> +--- 1> 0 | +--- (base class A) 1> 0 ...

  10. Flutter2.X学习之路--调试页面布局好用的办法

    Flutter里有个很好用的东西,可以方便我们来进行页面组件的布局调试,话不多说,上代码 1.找到main.dart引入rendering.dart import 'package:flutter/r ...