1 条题解
-
0
题目大意:
给定一个序列,求出一个最长的序列 ,使得其中最大值与最小值的差不超过 。
前置知识:
1.单调队列 。
思路:
这道题是一个区间问题,可以采用枚举左端点,快速查找右端点的思路。
由于 ,
所以,我们可以猜测,这道题是 的做法。那么 ,枚举左端点, 查找右端点,最常用的方法,是什么呢?
就是单调队列!
根据这道题的规定,不管有没有用,可以 处理出每个点右边的上升序列和下降序列。
考虑如何处理出右端点。
不能盲目查找,这时候,又一个区间常用策略来了,单调性。
对于一个以 为左端点, 为满足规定的最长的以 为左端点的序列,那么对于 ,左端点不需要 ,
因为 都已经不满足规定了,而集合的增大不会减小最大值,增大最小值,从而最大值与最小值的差永远 。
假设上升序列的对首为 ,下降序列为 ,假如 ,是移动 ,还是移动 呢 ?
想到规定当中的最长序列,那么假设 的位置 的位置,那么肯定是移动 最优,反之,同理。
代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; const int kMax=3e6+5; const int kInf=1e9; int k,n; int a[kMax]; int ans; int s1[kMax],s2[kMax],t1,t2,h1=1,h2=1;//s1递减,s2递增 int main(){ scanf("%d%d",&k,&n); for(int i=1;i<=n;++i){scanf("%d",&a[i]);} for(int i=1;i<=n;++i){ bool flag=1; while(t1>=h1&&a[s1[t1]]<=a[i]){t1--;} s1[++t1]=i; while(t2>=h2&&a[s2[t2]]>=a[i]){t2--;} s2[++t2]=i; while(a[s1[h1]]-a[s2[h2]]>k){ if(h1<t1&&s1[h1]<s2[h2]){h1++;} else if(h2<t2){h2++;} else{flag=0;break;} } if(flag){ans=max(ans,i-max(s1[h1-1],s2[h2-1]));} } printf("%d\n",ans); return 0; }
- 1
信息
- ID
- 3761
- 时间
- 1000ms
- 内存
- 64MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者