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 }