// hdu3530 Subsequence 单调队列
// 题目大意:找到一个最大的子串,使得子串区间内最大值和最小值的差
// 在low和up范围内,串的规模10w。
// 解题思路:
// 单调队列,单调队列可以保留i位置之前的最大值和最小值的下标,有了这些
// 则,每次我们比较两个队列的队头,看差值是否大于up,(因为它是到i位置最大
// 的差值,其他值不可能比i还要大.)
// 如果大于,则将两个对头靠前的那个丢掉,即出队,再比较对头,并且记录下
// 出队的位置下标,(因为此时出队的与到i的串的左边界有关),之后就是在
// 到i为止的最大值最小值之差如果大于等于low,这时i-上面记录的出队的较大
// 的位置就是到i的串的最大的长度。
// 感悟:
// 这道题想到了用两个单调队列分别保留最大值和最小值,但是出队的顺序,我并没有
// 很清楚,只知道一定会出队的,我之前的考虑是对两个对头比较,这是毫无疑问的,
// 之后对那个进行++操作呢,如果一起加,肯定是有问题,所以不是很清楚。之后看了看
// 各位大神的结题报告,发现,哪个在前面就出去就可以了,最后出队的取个最大的就是
// 左边界-1的值。
// 行百里者半九十,恰恰是最后的十让人撕心裂肺,欲罢不能,继续加油
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
const int MAX_N = 1e5 + 1000;
int n,low,up;
int a[MAX_N];
int deqmi[MAX_N];
int deqmx[MAX_N];
void input(){
for (int i = 1;i <= n; i++){
cin >> a[i];
}
}
void solve(){
int head1 = 0,tail1 = 0;
int head2 = 0,tail2 = 0;
int mx = 0;
int last1=0,last2=0;
for (int i=1;i<=n;i++){
while(head1 < tail1 && a[deqmi[tail1-1]] >= a[i])
tail1--;
deqmi[tail1++] = i;
while(head2 < tail2 && a[deqmx[tail2-1]] <= a[i])
tail2--;
deqmx[tail2++] = i;
while(a[deqmx[head2]] - a[deqmi[head1]]>up){
// while(head1 < tail1 && a[deqmx[head1]] - a[deqmi[head2] >= )
if (deqmx[head2]>deqmi[head1]){
last1 = deqmi[head1++];
}else {
last2 = deqmx[head2++];
}
}
if (a[deqmx[head2]] - a[deqmi[head1]] >= low){
mx = max(mx,i-max(last1,last2));
}
}
cout << mx << endl;
}
int main(){
ios::sync_with_stdio(false);
while(cin >> n >> low >> up){
input();
solve();
}
}
hdu3530 Subsequence 单调队列
最新推荐文章于 2021-01-22 20:35:01 发布