hdu 3530 Subsequence 单调队列

题目链接

题目给出n个数, 一个下界m, 一个上界k, 让你求出最长的一段序列, 满足这段序列中的最大的数-最小的数<=k&&>=m, 输出这段长度。

可以维护两个队列, 一个队列的队头元素是这一段中的最大值,是一个单调递减的数列; 另一个队列是这段中的最小值, 单调递增的数列。具体看代码。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 1e5+5;
 4 int a[maxn], q1[maxn], q2[maxn];
 5 int main()
 6 {
 7     int n, m, k;
 8     while(cin>>n>>m>>k) {
 9         for(int i = 0; i<n; i++) {
10             scanf("%d", &a[i]);
11         }
12         int st1 = 0, st2 = 0, ed1 = 0, ed2 = 0, ans = 0, now = 0;
13         for(int i = 0; i<n; i++) {
14             while(st1<ed1&&a[q1[ed1-1]]<a[i])       //q1维护一个单调递减的数列,这样队头元素是最大值, 第二个是第二大的值
15                 ed1--;
16             while(st2<ed2&&a[q2[ed2-1]]>a[i])       //q2维护一个单调递增的数列, 队头是最小值。
17                 ed2--;
18             q1[ed1++] = q2[ed2++] = i;              
19             while(st1<ed1&&st2<ed2&&a[q1[st1]]-a[q2[st2]]>k) {      //如果最大值-最小值大于k
20                 if(q1[st1]<q2[st2]) {
21                     now = q1[st1++]+1;                 //如果最大值在序列中的位置小于最小值
22                 } else {
23                     now = q2[st2++]+1;
24                 }
25             }
26             if(st1<ed1&&st2<ed2&&a[q1[st1]]-a[q2[st2]]>=m) {
27                 ans = max(ans, i-now+1);                //只有最大值-最小值大于等于m的时候才更新ans
28             }
29         }
30         cout<<ans<<endl;
31     }
32 }

 

posted on 2015-12-12 10:44  yohaha  阅读(533)  评论(0编辑  收藏  举报

导航