hdu 3530 "Subsequence" (单调队列)
题意:
给出一个序列,求最长的连续子序列,使得 m ≤ Max-Min ≤ k
我的理解:
定义数组 a[] 存储输入的 n 个数;
定义两个双端队列:
deque<int >qMax,qMin;
qMax : 维护前 i 个数的最大值(非递增序列);
qMin : 维护前 i 个数的最小值(非递增序列);
for(int i=;i <= n;++i)
{
///注意此处用了'=',也就是说,队列中的所有数都互异
while(!qMax.empty() && a[qMax.back()] <= a[i])
qMax.pop_back();///保证qMax递减
qMax.push_back(i);
while(!qMin.empty() && a[qMin.back()] >= a[i])
qMin.pop_back();///保证qMin递增
qMin.push_back(i);
}
例如:
1 2 3 4 5 6
val: 9 6 5 1 2 3
i = 6 时的队列情况(此处队列中维护的是值,便于理解):
qMax : {9,6,5,3};
qMin : {1,2,3};
假设来到 i 位置(队列维护下标):
qMax : { φ1,φ2,φ3,...,i };(下标递增,下标对应的值递减)
qMin : { ω1,ω2,ω3,....,i }:(下标递增,下标对应的值递增)
(φ1,φ2,φ3,...ω1,ω2,ω3 互不相同,当然 i 除外)
(qMax.val ≥ qMin.val,下标对应的值)
下面看看队列的操作(pos初始为1):
while(a[qMax.front()]-a[qMin.front()] > k)
{
if(qMax.front() < qMin.front())
{
pos=qMax.front()+;
qMax.pop_front();
}
else
{
pos=qMin.front()+;
qMin.pop_front();
}
}
if(a[qMax.front()]-a[qMin.front()] >= m)
ans=max(ans,i-pos+);
首先判断 qMax.front() 对应的值(假设为 a[φ1]) 与 qMin.front() 对应的值(假设为 a[ω1])做差是否大于 k;
如果大于,那么,如何使差值变小呢?
操作①qMax.pop_front(),(φ1 -> φ2)下一位对应的值更小
操作②qMin.pop_front(),(ω1 -> ω2)下一位对应的值更大
操作①②都可以使他们两者的差值变小,那么,到底该用哪个操作呢?
答案:谁的下标小,弹出谁,并且,所有的出队操作是不可能使队列为空的,因为两个队列中都有a[ i ]这个元素;
为什么要这么做呢?
假设不这么做,那么就是谁的下标大,弹出谁,假设 φ1 > ω1 ;
那么,就需要弹出φ1 ,那么,包含当前最值的区间为[ ω1 ,φ2],但是,φ1 也在其中,最大值就不该是a[φ1 ]而应该是a[φ2];
所以,谁的下标小,弹出谁;
pos作用又是啥呢?
找到包含 a[ i ] 的,并且满足条件的最大的区间,也就是[pos,i]是包含a[i]的最大的区间;
那,为什么pos=front()+1就一定对呢?
假设当前弹出的是φ1 ,也就是说a[φ1]-a[ω1] > t,假设 a[φ2]-a[ω1] ≤ t;
那么,a[pos]-a[ω1] ≤ t;
因为a[pos] ≤ a[φ2],在 φ2 满足条件的情况下,pos一定满足条件,且是满足条件的最大的区间(φ1不满足);
为什么不用判断其是否 ≥ m 呢?
因为操作①②都是使差值减小,只有可能在后面的更新队列的操作中使其差值增大;
AC代码:
#include<iostream>
#include<cstdio>
#include<deque>
using namespace std;
const int maxn=1e5+; int n,m,k;
int a[maxn];
deque<int >qMax,qMin; int Solve()
{
qMax.clear();
qMin.clear(); int ans=;
int pos=;
for(int i=;i <= n;++i)
{
///注意此处用了'=',也就是说,队列中的所有数都互异
///不加'='也行,不影响答案,因为在弹出操作时,qMax,qMin都将等于a[i]的给去了
///那么,a[i]本身是不会更新pos的值
///就算是队列末尾有重复的a[i]也不会更新pos,这就保证了pos的正确性
///[pos,i]是包含a[i]的最大的区间
while(!qMax.empty() && a[qMax.back()] <= a[i])
qMax.pop_back();
qMax.push_back(i);
while(!qMin.empty() && a[qMin.back()] >= a[i])
qMin.pop_back();
qMin.push_back(i); while(a[qMax.front()]-a[qMin.front()] > k)///最坏的情况是最后两个队列只剩下a[i]
{
if(qMax.front() < qMin.front())
{
pos=qMax.front()+;
qMax.pop_front();
}
else
{
pos=qMin.front()+;
qMin.pop_front();
}
}
if(a[qMax.front()]-a[qMin.front()] >= m)
ans=max(ans,i-pos+);///判断[pos,i]区间是否更新ans
}
return ans;
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&k))
{
for(int i=;i <= n;++i)
scanf("%d",a+i);
printf("%d\n",Solve());
}
return ;
}
hdu 3530 "Subsequence" (单调队列)的更多相关文章
- HDU - 3530 Subsequence (单调队列)
Subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- hdu 3530 Subsequence 单调队列
题目链接 题目给出n个数, 一个下界m, 一个上界k, 让你求出最长的一段序列, 满足这段序列中的最大的数-最小的数<=k&&>=m, 输出这段长度. 可以维护两个队列, ...
- 【单调队列+尺取】HDU 3530 Subsequence
acm.hdu.edu.cn/showproblem.php?pid=3530 [题意] 给定一个长度为n的序列,问这个序列满足最大值和最小值的差在[m,k]的范围内的最长子区间是多长? [思路] 对 ...
- HDU 3530 Subsequence(单调队列)
传送门 Description There is a sequence of integers. Your task is to find the longest subsequence that s ...
- hdu 3530 Subsequence
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3530 Subsequence Description There is a sequence of i ...
- HDU 3401 Trade(单调队列优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3401 题意:炒股.第i天买入一股的价钱api,卖出一股的价钱bpi,最多买入asi股,最多卖出bsi股 ...
- Hdu 3410 【单调队列】.cpp
题意: 给出一个数组,问你对于第i个数,从最后一个比它大的数到它之间比它小的数中最大的那个数的下标,以及它右边到第一个比它大的数中比它小的数中最大的那一个数的下标<下标从1开始>. eg: ...
- HDU 5749 Colmerauer 单调队列+暴力贡献
BestCoder Round #84 1003 分析:(先奉上zimpha巨官方题解) 感悟:看到题解单调队列,秒懂如何处理每个点的范围,但是题解的一句算贡献让我纠结半天 已知一个点的up,do ...
- HDU 5289 Assignment(单调队列)
题意:给T足数据,然后每组一个n和k,表示n个数,k表示最大同意的能力差,接下来n个数表示n个人的能力,求能力差在k之内的区间有几个 分析:维护一个区间的最大值和最小值,使得他们的差小于k,于是採用单 ...
随机推荐
- mysql参数优化记录
服务器参数16G内存,4核CPUvim /etc/my.cnf 原: back_log=170 max_connections=600 max_user_connections=0 thread_co ...
- react用class关键字来创建组件
创建组件之前,首先学习一个ES6的写法,叫做展开运算符. 比如我这里有两个数组.如何将第二个数组o2中的所有属性导入到数组o1中呢?一个个输太麻烦,所以就用到了展开运算符. var o2={ age: ...
- undefined reference to `cv::VideoCapture
出现opencv链接的问题原因: 1. 路径设置不正确,caffe会优先搜索Makefile.config里面的环境设置 2. anaconda2装的opencv和配置的opencv路径不一致 比如, ...
- 微服务 Micro services
微服务 (Microservices) 是一种软件架构风格,它是以专注于单一责任与功能的小型功能区块 (Small Building Blocks) 为基础,利用模组化的方式组合出复杂的大型应用程序, ...
- 2.23日刷数论题后总结(题目整理自SCUT
第一道:Rightmost digit 求N^N次最后一个数字 快速幂mod10咯 代码如下: #include <cstdio> #define ll long long using n ...
- servlet篇 之 访问形式
get方式访问和post方式访问: get/post区别? 1) 参数传递 查询字符串(的形式)! get url?key1=value&key2=value 2) http协议 请求报文包 ...
- 人工智能将继续壮大,两会委员建议增加“AI+教育”支持板块
导读 今年上海两会期间,上海市政协委员.上海交通大学机械与动力工程学院教授范秀敏提交提案,建议政府在推进上海人工智能专项建设中,增加“AI+教育”专项支持板块,并鼓励集聚发展AI产业的各个区,在人工智 ...
- Luogu4389 付公主的背包(生成函数+多项式exp)
显然构造出生成函数,对体积v的物品,生成函数为1+xv+x2v+……=1/(1-xv).将所有生成函数乘起来得到的多项式即为答案,设为F(x),即F(x)=1/∏(1-xvi).但这个多项式的项数是Σ ...
- POJ3468/splay树/成段更新
板子题,正在努力看懂板子.. http://blog.csdn.net/acm_cxlove/article/details/7815019 http://www.cnblogs.com/kuangb ...
- Codeforces Round #514 (Div. 2) C. Sequence Transformation 思维构造
题意 给出一个1-n的集合 gcd 集合里面的所有数 得到的 一个 数 然后自己选择删去一个数 要使得到的数 构成的数列 的字典序最大 思路: gcd所有数 那gcd得到的数肯定要小于数 ...