Codeforces 1204D2. Kirk and a Binary String (hard version) (dp思路)
题目链接: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思路)的更多相关文章
- 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 ...
- D1. Kirk and a Binary String (easy version)
D1. Kirk and a Binary String (easy version) 01串找最长不降子序列 给定字符串s,要求生成一个等长字符串t,使得任意l到r位置的最长不降子序列长度一致 从后 ...
- Codeforces 1204D Kirk and a Binary String - 数学
题目传送门 传送门 群除我均会猜结论/找规律,sad.... 以下内容只保证代码能过system test,证明应该都是在纯口胡 约定下文中的$LIS$表示最长不下降子序列. 定义$zero(s)$表 ...
- 01串LIS(固定串思维)--Kirk and a Binary String (hard version)---Codeforces Round #581 (Div. 2)
题意:https://codeforc.es/problemset/problem/1204/D2 给你一个01串,如:0111001100111011101000,让你改这个串(使0尽可能多,任意 ...
- Codeforces 1107 E - Vasya and Binary String
E - Vasya and Binary String 思路:区间dp + 记忆化搜索 转移方程看上一篇博客. 代码: #pragma GCC optimize(2) #pragma GCC opti ...
- Codeforces1107E Vasya and Binary String 记忆化dp
Codeforces1107E 记忆化dp E. Vasya and Binary String Description: Vasya has a string \(s\) of length \(n ...
- 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 ...
- [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 ...
- 2019牛客多校第三场B-Crazy Binary String(前缀和+思维)
Crazy Binary String 题目传送门 解题思路 把1记为1,把0记为-1,然后求前缀和,前缀和相等的就说明中间的01数一样.只要记录前缀和数值出现的位置即可更新出答案. 代码如下 #in ...
随机推荐
- windows10 找回windows照片查看器的方法
突然发现windows10自带的图片查看器打开预览查看速度还是可以的,但是却找不到了,,,,, 下面就是如何找回 windows 图片查看器的操作了,只需要运行一个bat程序即可!!!!!! 随便新建 ...
- 解决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 即可永久生效,下次登录,中文就不会乱码了.
- pandas玩转excel-> (2)如何利用pandas读取excel数据文件
import pandas as pd #将excel文件读到内存中,形成dataframe,并命名为peoplepeople=pd.read_excel('D:/python结果/task2/Peo ...
- pyecharts包学习笔记
目录 pyecharts包简介 特性 or 优点 版本 pyecharts包简介 精巧的图表设计.原作者说,当数据分析遇到数据可视化的时候github,该包就诞生了. 可以批量,直观的输出可视化图标吧 ...
- 搜索字母a或A
Amy觉得英语课实在是无聊至极,他不喜欢听老师讲课. 但是闲着也是闲着,不如做点什么吧?于是他开始数英语书里的字母a和A共出现了多少次. 费了九牛二虎之力终于数完了. 作为一名软件工程专业大学生,他觉 ...
- The file is absent or does not have execute permission This file is needed to run this program
tomcat下载后发现startup.sh文件启动不了 原因: 没有权限 解决方案:chmod 777 *.sh
- HDFS写入数据
HDFS副本摆放策略 不同的版本副本摆放策略可能并不一致,HDFS主要采用一种机架感知(rack-ware)的机制来实现摆放策略. 由于不同的机架上节点间通信要通过交换机(switches),同一机架 ...
- 159.SQL注入的实现和防御措施
sql注入: 所谓sql注入,就是通过把sql命令插入到表单中或页面请求的查询字符串中,最终达到欺骗服务器执行恶意的sql命令.具体来说,它是利用现有的应用程序,将(恶意的)sql命令注入到后台数据库 ...
- 检测识别问题中的metrics
之前一直记不熟各种指标的具体计算,本文准备彻底搞定这个问题,涵盖目前遇到过的所有评价指标. TP,TN,FP,FN 首先是true-false和positive-negative这两对词.以二分类为例 ...
- 跨站点脚本攻击XSS
来源:http://www.freebuf.com/articles/web/15188.html 跨站点脚本攻击是一种Web应用程序的攻击,攻击者尝试注入恶意脚本代码到受信任的网站上执行恶意操作.在 ...