题目描述

给出 \(N\) 个正整数 \(a[1..N]\) ,再给出一个正整数 \(k\) ,现在可以进行如下操作:每次选择一个大于 \(k\) 的正整数 \(a[i]\) ,将 \(a[i]\) 减去 \(1\) ,选择 \(a[i-1]\) 或 \(a[i+1]\) 中的一个加上 \(1\) 。经过若干次操作后,问最大能够选出多长的一个连续子序列,使得这个子序列的每个数都不小于 \(k\) .

初步分析

其实这个题与下述题目等效:

给出 \(N\) 个正整数 ( \(a[i]-k\) ) 组成的序列,序列前 \(i\) 项和记为 \(s[i]\) ,求满足 \(s[i]> s[j]\) 且 \(i> j\) 的 \(j-i\) 的最大值.

我们来思考一下为什么两个问题会相等.

容易想到,只有平均数大于等于 \(k\) 的子序列经过操作后能够使其每个数都不小于 \(k\),等效于在 \(a[i]-k\) 构成的序列中求最大的和为非负的区间. 而区间和又等于 \(s[j]-s[i-1]\) ,即 \(s[j]-s[i-1]> 0\),整理得 \(s[j]> s[i-1]\),此时区间长度 \(j-i+1\) 即为答案.

因此,我们现在的问题就转化为,如何求这样的区间最大值.

区间最值

首先放出引理:若 \(s[i_{1}] < s[j],\ s[i_{2}]< s[j],\ i_{1} < i_{2} \le j\),那么 \(i_{2}\) 一定不是最优解.

根据此引理,我们定义有可能为最优解的条件:符合条件,且其左方没有符合条件的数.

所以,如果我们从左边遍历,遇到第一个符合条件的数,那么符合该条件的数只有它可能是最优解,所以我们直接改到下一个条件遍历.

总结出如下遍历步骤:

  • 设定初始条件为 \(s[j]=0\).
  • 从左向右尝试放入前缀和.
  • 当前前缀和满足 \(s[i] > s[j]\),放入,并将 \(s[i]\) 作为新的条件.
  • 不满足,忽略.

前缀和有正有负,那么为什么初始条件是 \(s[j]=0\) 呢. 这是为了防止将正的前缀和放进去. 因为实际上正的前缀和可以直接作为答案区间,不需要进行这步流程,我们把它放进去反而会跑错.

注意到此步骤可以用栈实现:

s.push(0);
for(int i=1;i<=n;++i){
sum[i]=sum[i-1]+a[i]-k;
if(sum[s.top()]>sum[id]){
s.push(id);
}
}

我们通过上述步骤,将栈内的内容维护成了一个严格单调递减的序列的下标,这样的话,只要满足 \(i < j\),就有 \(s[i]<s[j]\).

接下来我们来考虑如何求最大区间.

由上述引理,我们倒序遍历全部前缀和 \(s[i]\) , 设栈顶前缀和为 \(s[top]\),那么我们可以遍历到满足 \(s[top]<s[i]\) 的最后一个数,此时区间长度即为 \(i-top\).

代码实现

stack<long long> s;
long long a[1000001],sum[1000001];
void push(int id){
if(sum[s.top()]>sum[id]){
s.push(id);
}
}
long long calc(int n){
long long ans=0;
for(int i=n;i>=1;--i){
while(!s.empty()&&sum[i]-sum[s.top()]>=0){
ans=max(ans,i-s.top());
s.pop();
}
}
return ans;
}
int main(){
int n,m,k;
cin>>n>>m;
for(int i=1;i<=n;++i){
cin>>a[i];
}
for(int i=1;i<=m;++i){
cin>>k;
s.push(0);
for(int i=1;i<=n;++i){
sum[i]=sum[i-1]+a[i]-k;
push(i);
}
s.push(n);
cout<<calc(n)<<" ";
while(!s.empty()){
s.pop();
}
}
}

[TK] Blocks 单调栈的更多相关文章

  1. bzoj 2086 [Poi2010]Blocks 单调栈

    [Poi2010]Blocks Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 788  Solved: 356[Submit][Status][Dis ...

  2. bzoj2086: [Poi2010]Blocks DP,单调栈

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2086 思路 这就有点妙了 题目意思就是让你求平均数>=k的最长序列 先求出a[i] ...

  3. poj 3415 Common Substrings(后缀数组+单调栈)

    http://poj.org/problem?id=3415 Common Substrings Time Limit: 5000MS   Memory Limit: 65536K Total Sub ...

  4. POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数

    题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS   Memory Limit: 65536K ...

  5. [bzoj2086][Poi2010]Blocks_单调栈_双指针

    Blocks bzoj-2086 Poi-2010 题目大意:题目链接. 注释:略. 想法:首先,不难发现,如果连续的一段数的平均值不小于输入的k的话,这段数是满足题意的. 所以,我们再次简化一下:将 ...

  6. POJ - 3415 Common Substrings(后缀数组求长度不小于 k 的公共子串的个数+单调栈优化)

    Description A substring of a string T is defined as: T( i, k)= TiTi+1... Ti+k-1, 1≤ i≤ i+k-1≤| T|. G ...

  7. BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 8748  Solved: 3835[Submi ...

  8. BZOJ 4453: cys就是要拿英魂![后缀数组 ST表 单调栈类似物]

    4453: cys就是要拿英魂! Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 90  Solved: 46[Submit][Status][Discu ...

  9. BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2326  Solved: 1054[Submit][Status ...

  10. poj 2559 Largest Rectangle in a Histogram - 单调栈

    Largest Rectangle in a Histogram Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19782 ...

随机推荐

  1. STM32开发环境配置记录——关于PlatformIO + VSCode + CubeMX的集成环境配置

    前言 ​ 为什么配置这样的一个环境呢?鄙人受够了Keil5那个简陋的工作环境了,实在是用不下去,调试上很容易跟CubeMX的代码产生不协调导致调试--发布代码不一致造成的一系列问题.CubeIDE虽说 ...

  2. ipa文件上传到app store的构建版本的工具

    打包好ipa文件后,可以使用mac电脑上的xcode将ipa上传到app store的构建版本中,假如没有mac电脑,可以使用香蕉云编来将ipa文件上传到构建版本. 这里我们来介绍下ipa文件上传到a ...

  3. Zabbix 5.0 LTS 配置企业微信(Webhook)自动发送告警信息

    依据前面文章<Zabbix 5.0 LTS URL 健康监测>环境,实现企业微信(Webhook)自动发送告警信息. 一.创建企业微信机器人 先在自己的企业微信群里创建一个机器人,并获取其 ...

  4. docker 安装 centos8 mysql8 java tomcat

    docker 安装 centos8  mysql8  java tomcat 一,首先在window10系统安装docker,这里就不再描述了. 二,启动docker下载安装centos8镜像 注意: ...

  5. 【DataBase】MySQL 12 SQL函数 聚合函数

    视频参考自:P53 - P58 https://www.bilibili.com/video/BV1xW411u7ax 什么是分组函数? 用来统计使用,其具体的实现都是基于对字段的值聚合再处理 又称为 ...

  6. 【Vue】Re09 Webpack 第一部分(介绍、安装、配置)

    一.Webpack的用途 webpack要解决的是统一网页资源的问题 前端工程化出现了很多问题,就是兼容性,浏览器所不能解析 所以需要一个打包,转换等方式处理 二.安装描述介绍 下载安装NodeJS, ...

  7. SourceGenerator 生成db to class代码优化结果记录 二

    优化 在上一篇留下的 Dapper AOT 还有什么特别优化点的问题 在仔细阅读生成代码和源码之后,终于得到了答案 个人之前一直以为 Dapper AOT 只用了迭代器去实现,所以理应差不多实现代码却 ...

  8. 使用 onNuxtReady 进行异步初始化

    title: 使用 onNuxtReady 进行异步初始化 date: 2024/8/16 updated: 2024/8/16 author: cmdragon excerpt: 摘要:本文详细介绍 ...

  9. 自己实现一个自动检测网卡状态,并设置ip地址,源码见文章底部

    阅读本文前,请先学习下面几篇文章 <搞懂进程组.会话.控制终端关系,才能明白守护进程干嘛的?> <简简单单教你如何用C语言列举当前所有网口!> <Linux下C语言操作网 ...

  10. 仿MFC消息机制封装对话框窗口类

    仿MFC消息机制封装对话框窗口类 这几天,又看了网上不少MFC的学习视频,学习了不少知识,对MFC消息机制有了不少的认识,于是便有了根据MFC消息机制再次封装一次对话框类, class QDialog ...