题目再次链接

题意:

  已知01序列a,求进行定长子串取反的最少操作次数,以及最少时的定长。

分析:

  首先,先想一想怎么暴力吧。这样想:要保证最小,那么必然不会对同一个区间反转两次,而在k一定时,则不会以同一个数为起点反转两次,于是我们有如果第一个数是0,则反转,是1,则不反转,第一个是否反转就可以确定了,然后按照反转操作进行反转,反转完之后再判断第二个,一直到最后一个(如果区间后端超了n,那么将不会反转成功),然后我们枚举k找到满足条件的k,以及其反转次数。

  暴力还是比较简单的,就是枚举+模拟,但是这样的复杂的接受不了。怎么办呢,我们想想可以对哪个环节进行优化,枚举环节好像没啥,该枚举还是要枚举。

  那模拟环节呢,你会发现,其实我们判断他需不需要改变是1的,只不过是模拟改变的过程还要走一遍k,这是复杂度无法接受的原因,那么我们能不能在保证判断是1的情况下改掉模拟修改的复杂度,当然不一定是模拟,总之要找一种方法记录下来修改保证判断操作是1.

  其实还是比较好想到的:因为我们在判断i的过程中只需考虑它前面k-1个区间的修改次数,这个就相对好记录了,边判断边记录就可以了,这样维护它被修改的次数的操作也变为1了。问题就迎刃而解了。

代码:

 

#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
const int maxn=+;
bool a[maxn];
int f[maxn];
int sum[maxn];
int Co(int k,int n){
memset(f,,sizeof(f));
memset(sum,,sizeof(sum));
for(int i=;i<=n;i++){
bool js=a[i];
if((sum[i-]-sum[(i-k)>?(i-k):])%)
js=!js;
if(js){
if(i+k->n)
return -;
f[i]=;
}
sum[i]=f[i]+sum[i-];
}
return sum[n];
}
int main(){
int n;
scanf("%d",&n);
char js;
for(int i=;i<=n;i++){
scanf(" %c",&js);
if(js=='B')
a[i]=;
}
int k;
int jsjs;
int ans=1e9;
int ans2;
for(k=n;k>=;k--)
if(jsjs=Co(k,n)+){
if(jsjs-<ans){
ans=jsjs-;
ans2=k;
}
}
printf("%d %d",ans2,ans);
return ;
}//注释就暂时不写啦

最新文章

  1. 我的第一个FluentNHibernate例子
  2. Android总结篇系列:Android Intent
  3. EBS R12重启后无法进入登录页面
  4. Hadoop - 任务调度系统比较
  5. SAM4E单片机之旅——19、CAN间通信
  6. C++之路起航——标准模板库(set)
  7. phalcon: crypt-encrypt/decrypt用法
  8. c# ref关键字对于引用类型传递的影响
  9. chrome偶尔弹出新窗口的解决方案
  10. keepalived 安装和配置
  11. CCIE路由实验(4) -- BGP路由控制
  12. 如何有效的遍历django的QuerySet
  13. 3505: [Cqoi2014]数三角形
  14. Jenkins修改管理员密码
  15. 选择结构if、switch
  16. 2019-04-23-day038-数据库的语句
  17. gunicorn启动flask项目的坑
  18. RMAN-06059(转)
  19. 【jQuery源码】select方法
  20. mysql笔记--group by,limit用法

热门文章

  1. Linux笔记(第一天)
  2. STL中常用算法
  3. KVM NAT(网络地址转换模式)
  4. k8s学习-集群调度
  5. 03-Python基础2
  6. ubuntu18.04安装qt时候的错误解决
  7. 如何在本地搭建微信小程序服务器
  8. 50道Java集合经典面试题(收藏版)
  9. sed中使用shell变量
  10. Tensorflow中Tensor对象的常用方法(持续更新)