题目传送门
传送门
群除我均会猜结论/找规律,sad....
以下内容只保证代码能过system test,证明应该都是在纯口胡
约定下文中的$LIS$表示最长不下降子序列。
定义$zero(s)$表示串$s$中0的个数,$one(s)$表示$s$中1的个数。
约定字符串的下标从1开始。$s_{l, r}$表示$s$的$l$个字符开始到第$r$个字符组成的子串。
定义一个串$s$是fixed string,当且仅当满足下面任意一个条件:
- $s$是一个空串
- $s = 1t0$, 并且$t$是一个fixed string。
- $s = pq$,并且$p,q$都是非空fixed string。
不难根据定义证明:fixed string必定满足0和1出现次数相同,fixed string的串长总是偶数。
引理1 fixed string的LIS长度等于长度的一半。
证明 考虑使用归纳法来证明。为了方便起见,以下的$k$默认为偶数,因为是奇数的时候等价于为$k - 1$时的命题。
当串长为0的时候显然成立。
假设当串长小于等于$k$时成立,考虑串长等于$k + 2$的时候。设这个fixed string为$s$。
- 若$s = 1t0$,那么有:
$$
\begin {align}
LIS(1t0) &= \max\{LIS(1t), LIS(t0), LIS(t)\} \\
&= \max \{\max\{1 + one(t), LIS(t)\}, \max\{zero(t) + 1, LIS(t)\}, LIS(t)\} \\
&= \frac{|t|}{2} + 1 \\
&= \frac{|s|}{2}
\end{align}
$$ - 若$s = pq$。考虑无论在LIS在$p$中是怎么样的,$q$中至多只能选出$\frac{|q|}{2}$个数。
所以有$LIS(s) \leqslant \frac{|s|}{2}$,又因为全取0或全取1可以达到这个上界,所以有$LIS(s) = \frac{|s|}{2}$。
定理2 如果$s$是一个fixed string,那么不存在另一个01串$t$,满足
- $s\neq t$
- $s$的所有子串和$t$的所有子串的LIS长度相同。
证明 仍然考虑归纳法证明。
显然, 当是空串的时候显然成立。
假设当串长小于等于$k$时成立,考虑串长等于$k + 2$的时候。假设存在一个串$s'$满足条件。
- 如果$s = pq$,设$s' = ab\ (|a| = |p|, |b| = |q|)$,那么根据归纳假设有$a = p, b = q$。
- 如果$s = 1a0$。不难得到$s' = bac$,其中$b,c$是一个字符。
如果$s' = 0a0$或者$s' = 1a1$或者$s' = 0a1$,那么整个串的LIS长度为$|s|/2 + 1$。
因此不存在这样的$s'$
所以如果一个子串是fixed string,那么答案中它不会改变。
考虑怎么找到一些fixed string。
定义$D(s) = one(s) - zero(s)$,定义$f(s) = \max_{1 \leqslant i\leqslant |s|} D(s_{i:|s|}) $。如果$s$是一个空串,那么约定$f(s) = 0$
定理3 $s$是一个fixed string当且仅当
- $one(s) = zero(s)$
- $f(s) = 0$
证明 必要性 第一条显然。
第二条考虑用归纳法证明。
当$s = 1t0$,
$$
\begin{align}
f(1t0) &= \max\{0, f(t0)\} \\
&= \max \{0, f(t) - 1\} \\
&= 0
\end{align}
$$
当$s = pq$,有$f(pq) = \max\{f(p) + zero(q) - one(q), f(q)\} = 0$。
充分性 当$s$是一个空串的时候结论显然成立。
假设$ \max_{1 \leqslant i\leqslant |s|} D(s_{i:|s|})$在$i = j > 1$时取到了0,那么$s_{1 : j - 1}, s_{j, |s|}$显然满足两个条件。
否则$s = 1t0$,如果第一位为0,那么说明,$f(s) > 0$,矛盾。所以第一位一定为$1$。如果最后一位为1,那么也说明$f(s) > 0$。
因为$f(t0) < 0$,所以有$f(t) \leqslant 0$,因为$t$有相等的0和1,所以$f(t) = 0$。
引理4 串$s$不存在任何fixed string当且仅当不存在一个1在某个0的前面。
证明 否则考虑某对相邻的$10$。
考虑这样一个做法:
#includeusing namespace std; typedef bool boolean; int n; char s[100005]; int main() { int sum = 0; scanf("%s", s + 1); n = strlen(s + 1); for (int i = n; i; i--) { (s[i] == '0') ? (--sum) : ((!sum) ? (s[i] = '0') : (++sum)); } puts(s + 1); return 0; }
显然它将不在fixed string中的1都变为0。
显然它是答案的一个上界。因为fixed string中的字符不能改动,剩下的把1都变成0。
现在我们来证明它合法并且它同时也是答案的一个下界并且它一定合法。
考虑
$$
\begin{align}
LIS(s) = zero(s) + \max \{0, \max_{1\leqslant k\leqslant |s|} one(s_{k:|s|}) - zero(s_{k:|s|}) \}
\end{align}
$$
考虑如果每次我们只将一个1改为0,那么怎样会使得某个包含它的串$t$的LIS长度不会改变。
注意到$zero(t')$一定会增加1,那么后面的函数必须减少1。
假设我们修改的位置是$i$,那么函数$g(k) = one(t_{k:|t|}) - zero(s_{k:|t|})$,在$[1, i]$的取值会减少2。
这意味着,如果我只修改把一个1改为0,那么必须要使得$\max_{k > i} g(k)$等于最大值减1。
那么回到原串,修改一个不在fixed string中的位置$i$,等于对所有包含它的子串都要满足条件。
考虑每次选择在交界处的1,把它改为0,考虑任意一个从$l$开始在$j$结束且包含修改位置$i$的子串,那么有:
考虑$l$所截断的fixed string,这是一个fixed string的后缀。它的后缀最大值小于等于0。所以不会改变后缀最大值。下面将不再考虑这一部分。
因为$i$左侧存在不在fixed string中的0,所以根据fixed string的性质有$\max_{l\leqslant k \leqslant i} D(s_{k, j}) = D(s_{i, j})$。
考虑$j$所截掉的fixed string,这是一个fixed string的前缀,它仍然满足后缀最大值等于它本身的$D$函数值。
在这个被截掉的fixed string之前,后缀最大值会改变当且仅当遇到不在fixed string中的1,这个变化显然是连续的。
因此最大值在$i$处取到,并且存在一个值等于最大值减1。
这样就证明那是答案的一个下界。