// 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(); } }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-11-05 13:37:56