题意:

给定一串01串,m次询问,每次询问给你一个数k。k为对于这个01串所能进行的最多次操作,每次操作可以将该串中任意一个位置的数移到任意一个其他的位置。

每次询问之后,输出在这个操作数之内,所能达到的最长的连续0的长度。

思路:

一开始考虑的是尺取法进行求解,然后和队友一起debug了一整场...宣告凉凉...

我和队友的思路是如果遇到1,就把它移掉;然后对于该状态,再用剩余可操作数来更新ans,看上去好像是个好想法,但是仔细去想的话,就会发现这是不可行的。

例如,你现在尺取的长度是L...x...y...R,[L,R] 这个区间,但是最优解却是在 [x,y] 这个区间,那你就取不到这个区间了。由此尺取法就错了。

还是对于尺取的核心理解的不透彻,尺取法要求你尺取时左右端点右移的指标是一个单调性的指标,而本题中显然指标不单调,由此尺取不可行。

既然尺取不可行,那么我们就需要重新来看看这个序列了。

由于这是一个01串,很自然地可以想到记录前缀和来记录区间内一共有多少个1的问题,由此我们记录给每一个点都记录一个前缀和。

那么对于区间 [L+1,R] ,本题的结果是什么呢?可以发现本题的结果应该是【K次操作】

ans = R-(L+1)+1-(sum[R]-sum[L])+K-(sum[R]-sum[L])

化简后,可以得到

ans = (R-2*sum[R])-(L-2*sum[L])+K

由此,我们对于每一个点都维护一个a[i] = ans,然后用单调队列进行更新即可。

还记得单调队列吗,维护一个单调递增的单调队列就是对于当前要扔进来的i值,判断队尾元素是否大于等于这个值,假如大于等于这个值,就执行r--的操作,直到队尾元素比这个值小的时候,执行 q[++r] = i 操作,即将当前这个值扔到队尾。

然后再判断队首元素和队尾元素之间间隔的0的个数,如果间隔的0的个数大于K,则 l++,直到队首元素和队尾元素之间间隔的0的个数小于K为止。

然后往队列中添加元素,就更新一遍 ans 的答案,即可求出正解。

反思:

还是没有站在题意本身进行思考,以及对于尺取的本质掌握的不够深入,才导致对于算法判断错误,从而最终也没搞出这道题。

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define rep(i,a,b) for(int i = a;i <= b;i++)
using namespace std;
const int N = 1e6+1000;char s[N];
int m,n;
int a[N];
int sum[N];
int q[N];
int cnt;void solve(int k)
{int ans = 0;q[1] = 0;int l = 1, r = 1;rep(i,1,n){  while(l <= r && a[q[r]] >= a[i]) r--;q[++r] = i;while(l <= r && sum[i]-sum[q[l]] > k) l++;ans = max(ans,a[q[r]]-a[q[l]]+k);}printf("%d\n",min(ans,cnt));
}int main()
{while(~scanf("%s",s)){cnt = 0;scanf("%d",&m);int len = strlen(s);n = len;sum[0] = 0;a[0]=0;rep(i,1,len){if(s[i-1] == '0'){sum[i] = sum[i-1];cnt++;} else sum[i] = sum[i-1]+1;a[i] = i-2*sum[i];}rep(i,1,m){ int x;scanf("%d",&x);solve(x);}}return 0;
}

【Gym - 101234J】Zero Game【单调队列】相关推荐

  1. CTU Open Contest 2016 Suspicious Samples(单调队列)

    题目链接 http://codeforces.com/gym/101505/attachments 题目大意 按时间顺序给你n个点, 每个点有一个时间t, 和值v. 我们要把所有点和规定时间内所有点进 ...

  2. 单调队列多重背包时间复杂度O(vn)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 多重背包问题: 有N种物品和容量为V的背包,若第i种物品,容量为v[i],价值为w[i],共有n[i]件.怎样装才能使背包内的物品总价值最大? 网 ...

  3. 洛谷 P2219修筑绿化带 二维单调队列~

    题目链接:https://www.luogu.org/problem/P2219 emmm调了一个上午+中午,fan 题意:从N*M的中找到一个a*b的大矩形和减去a*b中的一个与之不重边界的c*d的 ...

  4. P2216 理想的正方形 单调队列 (二维)

    题目链接:https://www.luogu.org/problem/P2216 题意:求给定n*m的矩形中所有k*k的正方形块中最大值最小值之差(极差)最小 哇,大神的思路真的很帅 单调队列对每一行 ...

  5. 点分治问题 ----------- luoguP2942 [WC2010]重建计划 [点分治 + bfs + 单调队列 + 预处理建树 + 二分 + 01分数规划]

    题目链接 解题思路: 1.对于这个Avgvalue=∑e∈sv(e)∣s∣Avgvalue = \frac{\sum_{e\in s}v(e)}{|s|}Avgvalue=∣s∣∑e∈s​v(e)​ ...

  6. 解题报告:Fake Maxpooling(单调队列求矩阵的和)

    我们不妨先把这个问题中二维的矩阵简化成一维的数列.那么现在的问题就变成了一个求连续的滑动窗口最值问题:给出一个长度为n的数列和一个长度为k(k<n)的窗口,记录滑动窗口位于每个位置下的下的最大值 ...

  7. 0x12.基本数据结构 — 队列与单调队列

    目录 一.队列 0.UVA540 团体队列 Team Queue 1.AcWing 133. 蚯蚓(模拟优先队列) 二 .单调队列 0.AcWing 135. 最大子序和(单调队列) 1.luogu ...

  8. 【题解】P1419 寻找段落(二分+单调队列)难度⭐⭐⭐★

    P1419 寻找段落 首先二分答案,即:二分最大平均值. 我们将a全部减去mid,问题转化为判断是否存在一个长度在s~t范围内的区间它的和为正,如果有说明还有更大的平均值. 用前缀和和单调队列维护. ...

  9. 【数据结构】单调栈和单调队列 详解+例题剖析

    算法:单调栈和单调队列 一.单调栈和单调队列 二.单调栈例题 1.模板题入门 2.不懂不要急,看这道题 三.单调队列例题 1.入门 2.进阶 一.单调栈和单调队列 单调栈和单调队列与普通的栈,队列不同 ...

  10. HDU 5289 Assignment(单调队列)

    题意:给T足数据,然后每组一个n和k,表示n个数,k表示最大同意的能力差,接下来n个数表示n个人的能力,求能力差在k之内的区间有几个 分析:维护一个区间的最大值和最小值,使得他们的差小于k,于是採用单 ...

最新文章

  1. java中文乱码解决之道(二)—–字符编码详解:基础知识 + ASCII + GB**
  2. 想学Python,梦雅给你指一条明路!
  3. Sql Group by 使用
  4. react组件生命周期_React组件生命周期-挂钩/方法介绍
  5. Python3 Flask+nginx+Gunicorn部署(上)
  6. 【linux笔记】常用命令(2)目录
  7. IT部门域事件与业务分析
  8. PIL (Python Imaging Library) 教程
  9. win7休眠、待机api
  10. 51nod1359 循环探求
  11. 职场内耗,正在让这个团队瓦解
  12. tableSizeFor的理解
  13. 谈谈Google与微信H5牛牛的Java开发规范
  14. 985 大学老师的工资并没有很高,为什么大家都挤破头想进高校?
  15. 2021-6-9-今日收获
  16. 什么是Session 如何使用Session
  17. MindSpore数据集加载-GeneratorDataset数据处理报错:The pointer[cnode] is null
  18. Docker - 重新启动关闭的容器
  19. SqlServer-STUFF理解基础知识
  20. MongoDB基础教程笔记

热门文章

  1. ESTORE OPENCART 清爽现代主题模板 ABC-0063
  2. WPF开发时光之痕日记本(一)——富文本编辑器
  3. 误删除libc.so.6的解决方法
  4. cetnos6.4 基础版安装
  5. Hibernate上路_18-Hibernate查询方式
  6. Sql Server 分区之后增加新的分区
  7. 有了WCF,Socket是否已人老珠黄?
  8. STL中map与hash_map容器的选择
  9. vue设置isactive_Vue 编码风格指南!
  10. 缓冲大小 设置_【设计】小知识点:各种水箱的选型设计(二)缓冲水箱