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 ...
随机推荐
- (填坑系列) 用aio写server与client进行通信的坑
最近闲来无事,就估摸着自己写个“服务注册中心”来玩,当然因为是个人写的,所以一般都是简洁版本. 代码地址在:https://gitee.com/zhxs_code/my-service-registe ...
- WordPress 背后的故事竟然是这样
原文链接:The Story Behind the New WordPress.com 译者:杰微刊-Leo Xu 一年半以前,我们对使用 WordPress 构建网站所需要采用的技术和开发流程进行大 ...
- (转)预估大数据量下UV的方法
在实际应用中,我们经常碰到这种情况,即要统计某个对象或者事件独立出现的次数.对于较小的数据量,这很容易解决,我们可以首先在内存中对序列进行排序,然后扫描有序序列统计独立元素数目.其中排序时间复杂度为O ...
- Unity3D制作3D虚拟漫游场景(二)
传送门: Unity3D制作3D虚拟漫游场景(一) -------------------------------------------------------------------------- ...
- 基于Python的face_recognition库实现人脸识别
一.face_recognition库简介 face_recognition是Python的一个开源人脸识别库,支持Python 3.3+和Python 2.7.引用官网介绍: Recognize a ...
- linux切换普通用户遇bash-4.1解决
1,修改vim /etc/passwd 把对应用户的登陆环境改成,/bin/bash 2,复制配置 cp -a /etc/skel/. /home/www/ 3再次尝试su www有效
- python中os.sep的作用以及sys._getframe().f_back.f_code.co_xxx的含义
https://blog.csdn.net/gufenchen/article/details/98338552
- 【HTML】iframe嵌套界面自适应,可高度自由收缩
最近在做网页时需要使iframe高度自适应,以提高用户体验,网上找了挺多都很复杂,最后找到了这个 HTML: <div class="main_page"> <i ...
- 二、ZigBee无线网络
概述 ZigBee是基于IEEE802.15.4标准的低功耗局域网协议.根据国际标准规定,ZigBee技术是一种短距离.低功耗的无线通信技术.这一名称(又称紫蜂协议)来源于蜜蜂的八字舞,由于蜜蜂(be ...
- OpenCV的视频输入和相似度测量
#include <iostream> #include <string> #include <iomanip> // 控制浮动类型的打印精度 #include & ...