【CF1204D】Kirk and a Binary String【结论题】【LIS】

传送门

题意:给一个01串 S S S,求一个等长的01串 T T T

  1. S S S T T T所有对应位置的子串最长不下降子序列长度(以下简称 LIS \text{LIS} LIS)相同
  2. T T T中0的数量尽量多

∣ S ∣ ≤ 100000 |S| \leq 100000 S100000

对于一个01串 S S S,我们称它是固定的,当且仅当不存在一个长度相同的01串 T T T,它们所有对应位置的子串 LIS \text{LIS} LIS相同(即修改任意一个位置都会改变 LIS \text{LIS} LIS),并且规定空串是固定的。

  • 两个固定的串拼起来仍然是固定的。如果修改了一个位置,根据定义,这个位置原来归属的串的 LIS \text{LIS} LIS一定发生了变化。
  • 一个固定的串0和1个数相等, LIS \text{LIS} LIS等于其长度的一半,即全选0或全选1。前面和下一条递归证明,边界为空串。后面由于一组01(见下一条)的1一定在0的前面,最多只有1的贡献。
  • 一个固定的串前面添“1”,后面添“0”后仍然固定。和上一条递归证明,修改中间同理,修改两边一定会增加1。

我们在原串中删除所有极大的固定子串,由于没有“10”,所以剩下的一定是“00000……11111”

由定义,固定子串是不能修改的

【解法一】

我们发现这玩意就是括号匹配

用个栈维护一下,得到剩下的字符

然后把后面的一坨1都改成0。显然不能改更多的。

这样对于任意一个子串,把它的极大固定子串挖出来,由于后缀的“1”可能改成了“0”,把影响的段改成“全选0”后 LIS \text{LIS} LIS不会变化,可以保证合法。

【解法二】

结论:某个1可以改为0,当且仅当修改后整个串 LIS \text{LIS} LIS不变。

其实本质是相同的。如果某个位置的1在某个固定子串中,显然修改会改变这个子串的 LIS \text{LIS} LIS,并且会改变原串的 LIS \text{LIS} LIS。否则对 LIS \text{LIS} LIS不会产生影响。

倒着DP一下即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#define MAXN 100005
using namespace std;
char s[MAXN];
int pre0[MAXN],suf1[MAXN],dp[MAXN];
int main()
{
	scanf("%s",s+1);
	int n=strlen(s+1);
	for (int i=1;i<=n;i++) pre0[i]=pre0[i-1]+(s[i]=='0');
	for (int i=n;i>=1;i--) suf1[i]=suf1[i+1]+(s[i]=='1');
	for (int i=n;i>=1;i--) dp[i]=(s[i]=='1'? max(suf1[i],dp[i+1]):dp[i+1]+1);
	int now=0;
	for (int i=1;i<=n;i++)
		if (s[i]=='0'||now+1+dp[i+1]<=dp[1]) putchar('0'),++now;
		else putchar('1');
	return 0;
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值