题目链接:http://codeforces.com/contest/1204/problem/D2

题目是给定一个01字符串,让你尽可能多地改变1变为0,但是要保证新的字符串,对任意的L,R使得Sl,Sl+1,Sl+2...Sr的最长不递减子序列长度保持不变,求新的串s。

dp思路,从前往后遍历串s。

1 . 遇到s[ i ] = 0 是不能改变的,因为从i到n的最长不递减子序列必定是以s[ i ] = 0为起点的,改变之后会减少长度。

2 . 遇到s[ i ] = 1。我们考虑如果变为0,首先从0到 i-1 的最长不递减子序列是不受到影响的,因为从0到 i 的最长不递减子序列必定是以s [ i ] = 1为结尾的,不影响0到i -1 的最长不递减子序列,那么在0到i区间内, 我们需要保证条件1:任意的x(0<x<i)到 i 最长不递减子序列不发生改变,这里只要保证0到 i 的最长不递减子序列不变即可,任意的x(0<x<i)到 i 的最长不递减子序列就不会改变,因为0到x不会因为s[ i ]的变化受到影响,所以只要0到 i 的最长不递减子序列不发生改变,则x到 i 也不会改变。如果此时将s[ i ] 从1变成 0,要要0到 i 的最长不递减子序列不变,只有是以s[ i ] = 0为结尾的最长不递减子序列(原因上述有提到)的长度不变才可以,以s[ i ] = 0为结尾只能是一组0000...00,中间不能穿插1,所以其等价条件就是zeros + 1 == LIS1[ i ] (zeros表示从0到i中0的个数,LIS1表示0到i的最长不递减子序列),这里便满足条件1了。

需要满足的条件2:既然0到 i 已经保证,那么 i 到 n也是同样的道理,s[ i ] 由1变为0,此时 i 到n的最长不递减子序列势必是以s[ i ] = 0 为起点,其长度可以表示为LIS2[ i + 1 ]+1    // ( LIS2[ i +1 ] 表示i + 1 到n的最长不递减子序列) //。如果改变之前的最长不递减子序列是以s [ i ] = 1为起点,改变之后仍然以s[ i ] 为起点的话就没有问题,如果改变之前不是以S[ i ]为起点,改变之后从i到的n的最长不递减子序列必定会增加,因为i到n最长不递减子序列不管是以0为起点还是1为起点,当s[ i ] = 0时,肯定会与其拼接上,长度会+1。以上的等价条件就转化为 LIS2[ i ] == LIS2[ i +1 ] +1

满足以上两个条件的情况下,就可以使s[ i ] = 1变为0。

PS:在求解最长不递减子序列的过程中,如果用O(n^2)的算法对hard version会超时,easy version可以过。所以只能选择nlogn复杂度的算法。但是对于求LIS2[ i ] (i到n的最长不递减子序列),我没有想到相对简单的办法,因为不会lower_bound()的重载,所以只能选择较为麻烦的方法(具体看代码), 如果哪位朋友有更简便的做法可以留言一起交流一下。

AC代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#define maxn 100005
using namespace std;
int LIS1[maxn],LIS2[maxn],ones[maxn];
char low1[maxn],low2[maxn];//low[i]数组记录长度为i的最长不递减子序列结尾最小的元素
string s;
int zeros = 0,ans = 1;
int main(){
cin>>s;
LIS1[0] = 1,low1[1] = s[0];
for(int i = 1;i<s.length();i++){
if(s[i] >= low1[ans]){
low1[++ans] = s[i];
}
else{
int k = upper_bound(low1,low1 + ans + 1,s[i]) - low1 ;
low1 [k] = s[i];
}
LIS1[i] = ans;
}//用nlogn时间复杂度求从左到右求最长上升子序列 int cnt_one = 0;//从右到左记录1的个数
if(s[s.length() -1] == '1'){
cnt_one++;
}
ans = 1,LIS2[s.length() -1] = 1,low2[ans] = s[s.length()-1];
for(int i = s.length() -2;i>=0;i--){
if(s[i]<= low2[ans]){
low2[++ans] = s[i];//low2[++ans]中++ans长度的最长不递减子序列起始值改为s[i]
}
if(s[i] == '1'){
cnt_one++;//ans1记录1的个数
}
if(ans == cnt_one){
low2[ans] = '1';//贪心策略,如果此时ans和 cnt相等,
//把长度为 ans 的从左到右最长不递减子序列的起始值改为1,方便后续可以拼接0
}
LIS2[i] = ans;
}//从右到左,求i到s.length()-1的最长不递减子序列
for(int i = 0;i<s.length() ;i++){
if(s[i] == '0'){
zeros++;//前i个元素中0的个数
}
if(s[i] == '1'){
if(zeros + 1 == LIS1[i] && LIS2[i] == LIS2[i+1] + 1){
s[i] = '0';//如果两者相等,则可以把1改为0
zeros++;
}
}
}
cout<<s;
return 0;
}

Codeforces 1204D2. Kirk and a Binary String (hard version) (dp思路)的更多相关文章

  1. D2. Kirk and a Binary String (hard version) D1 Kirk and a Binary String (easy version) Codeforces Round #581 (Div. 2) (实现,构造)

    D2. Kirk and a Binary String (hard version) time limit per test1 second memory limit per test256 meg ...

  2. D1. Kirk and a Binary String (easy version)

    D1. Kirk and a Binary String (easy version) 01串找最长不降子序列 给定字符串s,要求生成一个等长字符串t,使得任意l到r位置的最长不降子序列长度一致 从后 ...

  3. Codeforces 1204D Kirk and a Binary String - 数学

    题目传送门 传送门 群除我均会猜结论/找规律,sad.... 以下内容只保证代码能过system test,证明应该都是在纯口胡 约定下文中的$LIS$表示最长不下降子序列. 定义$zero(s)$表 ...

  4. 01串LIS(固定串思维)--Kirk and a Binary String (hard version)---Codeforces Round #581 (Div. 2)

    题意:https://codeforc.es/problemset/problem/1204/D2 给你一个01串,如:0111001100111011101000,让你改这个串(使0尽可能多,任意 ...

  5. Codeforces 1107 E - Vasya and Binary String

    E - Vasya and Binary String 思路:区间dp + 记忆化搜索 转移方程看上一篇博客. 代码: #pragma GCC optimize(2) #pragma GCC opti ...

  6. Codeforces1107E Vasya and Binary String 记忆化dp

    Codeforces1107E 记忆化dp E. Vasya and Binary String Description: Vasya has a string \(s\) of length \(n ...

  7. CF1204D Kirk and a Binary String

    题目链接 problem 给出一个长度为\(n(n\le 10^5)\)的只包含01的字符串.把尽可能多的1变为0,使得对于所有的\(l \in [1,n],r\in [l,n]\),区间\([l,r ...

  8. [CF1107E]Vasya and Binary String【区间DP】

    题目描述 Vasya has a string s of length n consisting only of digits 0 and 1. Also he has an array a of l ...

  9. 2019牛客多校第三场B-Crazy Binary String(前缀和+思维)

    Crazy Binary String 题目传送门 解题思路 把1记为1,把0记为-1,然后求前缀和,前缀和相等的就说明中间的01数一样.只要记录前缀和数值出现的位置即可更新出答案. 代码如下 #in ...

随机推荐

  1. windows10 找回windows照片查看器的方法

    突然发现windows10自带的图片查看器打开预览查看速度还是可以的,但是却找不到了,,,,, 下面就是如何找回 windows 图片查看器的操作了,只需要运行一个bat程序即可!!!!!! 随便新建 ...

  2. 解决linux 终端UnicodeDecodeError: 'utf-8' codec can't decode byte 0xce in position 0: invalid continuation byte

    vi   /etc/locale.conf 修改LANG="zh_CN.gbk" 最后执行source /etc/locale.conf 即可永久生效,下次登录,中文就不会乱码了.

  3. pandas玩转excel-> (2)如何利用pandas读取excel数据文件

    import pandas as pd #将excel文件读到内存中,形成dataframe,并命名为peoplepeople=pd.read_excel('D:/python结果/task2/Peo ...

  4. pyecharts包学习笔记

    目录 pyecharts包简介 特性 or 优点 版本 pyecharts包简介 精巧的图表设计.原作者说,当数据分析遇到数据可视化的时候github,该包就诞生了. 可以批量,直观的输出可视化图标吧 ...

  5. 搜索字母a或A

    Amy觉得英语课实在是无聊至极,他不喜欢听老师讲课. 但是闲着也是闲着,不如做点什么吧?于是他开始数英语书里的字母a和A共出现了多少次. 费了九牛二虎之力终于数完了. 作为一名软件工程专业大学生,他觉 ...

  6. The file is absent or does not have execute permission This file is needed to run this program

    tomcat下载后发现startup.sh文件启动不了 原因: 没有权限 解决方案:chmod 777 *.sh

  7. HDFS写入数据

    HDFS副本摆放策略 不同的版本副本摆放策略可能并不一致,HDFS主要采用一种机架感知(rack-ware)的机制来实现摆放策略. 由于不同的机架上节点间通信要通过交换机(switches),同一机架 ...

  8. 159.SQL注入的实现和防御措施

    sql注入: 所谓sql注入,就是通过把sql命令插入到表单中或页面请求的查询字符串中,最终达到欺骗服务器执行恶意的sql命令.具体来说,它是利用现有的应用程序,将(恶意的)sql命令注入到后台数据库 ...

  9. 检测识别问题中的metrics

    之前一直记不熟各种指标的具体计算,本文准备彻底搞定这个问题,涵盖目前遇到过的所有评价指标. TP,TN,FP,FN 首先是true-false和positive-negative这两对词.以二分类为例 ...

  10. 跨站点脚本攻击XSS

    来源:http://www.freebuf.com/articles/web/15188.html 跨站点脚本攻击是一种Web应用程序的攻击,攻击者尝试注入恶意脚本代码到受信任的网站上执行恶意操作.在 ...