HDU - 3530 Subsequence(单调队列+思维)
题目链接:点击查看
题目大意:给出一段长度为n的序列,现在给出一个m和一个k,必须满足一段连续区间内的最大值与最小值的差值大于等于m并且小于等于k,问满足条件的连续区间的最大长度
题目分析:一开始看到连续区间就想到了尺取,用尺取写了一发直接WA掉了,后来想了一下,这个题目和尺取没什么关系,因为区间内的最大值和最小值并不会因为两个指针的移动而成线性的改变,他们的变化是无规律的,所以更不能二分了(或许可以二分,但绝对不是简单的二分),然后就不知所措了,去网上看了大佬的题解,发现可以直接维护两个单调队列,我们可以遍历一遍整个序列,然后以当前位置i为连续区间结束的位置,接下来我们该怎么找连续区间开始的位置呢?我们维护的两个单调队列,一个维护最大值,一个维护最小值,这样我们比较一下最大值和最小值的差,若其差值大于k的话,那么我们可以选择减小最大值或者增大最小值两个选项来缩小这个差值,选择哪一个选项取决与最大值和最小值的下标哪一个更靠前,这也是为了维护该连续区间的可行性,这样不断的将区间缩小,直到当前区间内的差值满足小于等于k这个条件,注意,若假设mmax.front()为最大值的下标,我们将其删掉后,可行区间变成了[mmax.front()+1,i],而不是[mmax.front(),i],注意一下这个+1
其实一开始我也是不太理解这个+1的,还是在这里再说一下我自己的理解吧,假设现在最大值和最小值之间的差值大于k,我们将要选择删掉最大值以减小差值,这样一来我们删掉的肯定是mmax.front()这个下标,若这个下标被删掉后,将会出现两种可能,新区间的最大值就是刚才被删除下标的后一位,另一种可能就是被删除下标的后一位并不是新区间的最大值,无论是这两种情况之中的哪一种,肯定都满足新区间中最大值和最小值之间的差值变小了,所以在删除掉第一个下标后新区间的范围变成了[mmax.front()+1,l],这样维护好整个区间后,我们最后判断一下这个差值是否大于等于m,若大于等于m,直接更新答案即可
有一个小细节,这个题目没有保证数据一定有解,会出现答案为0的情况,也就是所有区间都不满足条件,这个时候要输出0,我一开始看到题目要求最大值,就直接把答案设置为负无穷,这也导致我无解的情况会输出负无穷而不是0,因为这个小细节调了半个小时,也是有点自闭的
代码:
#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
#include<deque>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e5+100;int a[N];int main()
{
// freopen("input.txt","r",stdin);
// ios::sync_with_stdio(false);int n,m,k;while(scanf("%d%d%d",&n,&m,&k)!=EOF){for(int i=1;i<=n;i++)scanf("%d",a+i);deque<int>mmax;//维护最大值的单调队列,维护的是下标deque<int>mmin;//维护最小值的单调队列,维护的是下标int mark=1,ans=0;for(int i=1;i<=n;i++){while(mmax.size()&&a[mmax.back()]<=a[i])mmax.pop_back();mmax.push_back(i);while(mmin.size()&&a[mmin.back()]>=a[i])mmin.pop_back(); mmin.push_back(i);while(mmax.size()&&mmin.size()&&a[mmax.front()]-a[mmin.front()]>k)//如果差值大于k的话,删除掉最大值或最小值{if(mmax.front()<mmin.front()){mark=mmax.front()+1;//更新可行区间mmax.pop_front();}else{mark=mmin.front()+1;//更新可行区间mmin.pop_front();}}if(mmax.size()&&mmin.size()&&a[mmax.front()]-a[mmin.front()]>=m)//更新答案{ans=max(ans,i-mark+1);}}printf("%d\n",ans);}return 0;
}
HDU - 3530 Subsequence(单调队列+思维)相关推荐
- hdu 3530 Subsequence 单调队列
寻找一个区间,满足:其中的最大值减最小值在[m,k]的范围内,输出最大的区间长度. 思路:维护2个单调队列,一个递增,一个递减. 用一个now记录现在的区间的起点,如果大的数-小的数比k还大,则可以丢 ...
- hdu 3401 Trade(单调队列优化dp)
hdu 3401 Trade(单调队列优化dp) 题意:lxhgww喜欢炒股票,他可以在第i天买入或者卖出若干张股票(一天只能买或者卖),两个交易日之间至少相隔w天,问他t天后最多能赚多少. 解题思路 ...
- HDU 5289 Assignment(单调队列)
题意:给T足数据,然后每组一个n和k,表示n个数,k表示最大同意的能力差,接下来n个数表示n个人的能力,求能力差在k之内的区间有几个 分析:维护一个区间的最大值和最小值,使得他们的差小于k,于是採用单 ...
- HDU 3530 Subsequence
这道题很有意思,需要巧妙地套用单调队列 首先我们要明确几件事情 1.假设我们现在知道序列(i,j)是符合标准的,那么如果第j+1个元素不比(i,j)最大值大也不比最小值小,那么(i,j+1)也是合法的 ...
- HDU 6319(单调队列)
传送门 题面: Problem A. Ascending Rating Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 524288/ ...
- Fxx and game HDU - 5945(单调队列优化dp)
思路:考虑反着dp,从dp[1]倒推dp[x] 因为dp[i]<=dp[j] j<i ,所以考虑用单调队列来优化. 除法不用考虑,考虑加法就行. 代码: #include <bi ...
- 入门经典_Chap08_题解总结:极角扫描法 滑动窗口 单调队列 单调栈
总结 本章主要关注一个重要的问题 – 单调队列和单调栈的使用 同时还有一些其他的问题,如扫描法,递归的思想, 构造, 分治, 二分等 知识点 单调队列 和 单调栈 题目 UVA - 1606 Am ...
- 单调队列————[USACO09MAR]向右看齐Look Up
先了解一下单调队列: 很明显的具有单调性 分为单调递增和单调递减两种,简单点讲就是维护队头为最大值或者为最小值 (建议采用双向队列 比较好写) 具体步骤:(这个是单调递减) 如果队列非空且当前值比队 ...
- hdu 3706 Second My Problem First 单调队列
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3706 Second My Problem First Time Limit: 12000/4000 M ...
最新文章
- webservice中cxf框架的HelloWord
- Oracle的REGEXP_INSTR再mysql中实现
- FPGA之道(26)VHDL初始化
- leveldb java_LevelDB 代码撸起来!
- B03_NumPy创建数组(numpy.empty,numpy.zeros,numpy.ones)
- php_DBHelper
- 《统计学习方法》代码全解析——第十二部分监督学习方法总结
- 为何你仍是一名社畜码农?
- 最大,最小值问题,前K个数问题,利用mapreduce解决方案
- 2021年值得持续关注的10大网安工具
- 更新了 pe_xscan 和 ClosePc
- JMeter proxy server
- Spring 事务扩展机制 TransactionSynchronization
- python面向对象编程指南 豆瓣_Python面向对象编程
- 减法公式运算法则_加减法运算法则
- 数据化是什么,企业为什么要数据化管理?【Teamface企典】
- 计算机考研全国统考时段,考研初试各科目时间安排
- 免费获得minecraft账号,快来试试!!!
- 外贸软件对出口公司的作用
- mysql int等字段括号里的数字含义和作用