【Gym - 101234J】Zero Game【单调队列】
题意:
给定一串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【单调队列】相关推荐
- CTU Open Contest 2016 Suspicious Samples(单调队列)
题目链接 http://codeforces.com/gym/101505/attachments 题目大意 按时间顺序给你n个点, 每个点有一个时间t, 和值v. 我们要把所有点和规定时间内所有点进 ...
- 单调队列多重背包时间复杂度O(vn)
版权声明:本文为博主原创文章,未经博主允许不得转载. 多重背包问题: 有N种物品和容量为V的背包,若第i种物品,容量为v[i],价值为w[i],共有n[i]件.怎样装才能使背包内的物品总价值最大? 网 ...
- 洛谷 P2219修筑绿化带 二维单调队列~
题目链接:https://www.luogu.org/problem/P2219 emmm调了一个上午+中午,fan 题意:从N*M的中找到一个a*b的大矩形和减去a*b中的一个与之不重边界的c*d的 ...
- P2216 理想的正方形 单调队列 (二维)
题目链接:https://www.luogu.org/problem/P2216 题意:求给定n*m的矩形中所有k*k的正方形块中最大值最小值之差(极差)最小 哇,大神的思路真的很帅 单调队列对每一行 ...
- 点分治问题 ----------- luoguP2942 [WC2010]重建计划 [点分治 + bfs + 单调队列 + 预处理建树 + 二分 + 01分数规划]
题目链接 解题思路: 1.对于这个Avgvalue=∑e∈sv(e)∣s∣Avgvalue = \frac{\sum_{e\in s}v(e)}{|s|}Avgvalue=∣s∣∑e∈sv(e) ...
- 解题报告:Fake Maxpooling(单调队列求矩阵的和)
我们不妨先把这个问题中二维的矩阵简化成一维的数列.那么现在的问题就变成了一个求连续的滑动窗口最值问题:给出一个长度为n的数列和一个长度为k(k<n)的窗口,记录滑动窗口位于每个位置下的下的最大值 ...
- 0x12.基本数据结构 — 队列与单调队列
目录 一.队列 0.UVA540 团体队列 Team Queue 1.AcWing 133. 蚯蚓(模拟优先队列) 二 .单调队列 0.AcWing 135. 最大子序和(单调队列) 1.luogu ...
- 【题解】P1419 寻找段落(二分+单调队列)难度⭐⭐⭐★
P1419 寻找段落 首先二分答案,即:二分最大平均值. 我们将a全部减去mid,问题转化为判断是否存在一个长度在s~t范围内的区间它的和为正,如果有说明还有更大的平均值. 用前缀和和单调队列维护. ...
- 【数据结构】单调栈和单调队列 详解+例题剖析
算法:单调栈和单调队列 一.单调栈和单调队列 二.单调栈例题 1.模板题入门 2.不懂不要急,看这道题 三.单调队列例题 1.入门 2.进阶 一.单调栈和单调队列 单调栈和单调队列与普通的栈,队列不同 ...
- HDU 5289 Assignment(单调队列)
题意:给T足数据,然后每组一个n和k,表示n个数,k表示最大同意的能力差,接下来n个数表示n个人的能力,求能力差在k之内的区间有几个 分析:维护一个区间的最大值和最小值,使得他们的差小于k,于是採用单 ...
最新文章
- java中文乱码解决之道(二)—–字符编码详解:基础知识 + ASCII + GB**
- 想学Python,梦雅给你指一条明路!
- Sql Group by 使用
- react组件生命周期_React组件生命周期-挂钩/方法介绍
- Python3 Flask+nginx+Gunicorn部署(上)
- 【linux笔记】常用命令(2)目录
- IT部门域事件与业务分析
- PIL (Python Imaging Library) 教程
- win7休眠、待机api
- 51nod1359 循环探求
- 职场内耗,正在让这个团队瓦解
- tableSizeFor的理解
- 谈谈Google与微信H5牛牛的Java开发规范
- 985 大学老师的工资并没有很高,为什么大家都挤破头想进高校?
- 2021-6-9-今日收获
- 什么是Session 如何使用Session
- MindSpore数据集加载-GeneratorDataset数据处理报错:The pointer[cnode] is null
- Docker - 重新启动关闭的容器
- SqlServer-STUFF理解基础知识
- MongoDB基础教程笔记