题目大意:给定一个序列,求一个最长的子串,使最大值与最小值之差不超过k
从左到右枚举右端点,利用单调队列维护当前区间中的最大值和最小值
如果某一时刻当前区间的最大值和最小值之差超过了k,就向右调整左端点直到差小于等于k为止
时间复杂度O(n)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 3003003 using namespace std; int n,k,ans,a[M]; int q_max[M],r_max,h_max; int q_min[M],r_min,h_min; int main() { int i,j; cin>>k>>n; for(j=0,i=1;i<=n;i++) { scanf("%d",&a[i]); { int &r=r_max,&h=h_max,*q=q_max; while( r-h>=1 && a[q[r]]<a[i] ) q[r--]=0; q[++r]=i; } { int &r=r_min,&h=h_min,*q=q_min; while( r-h>=1 && a[q[r]]>a[i] ) q[r--]=0; q[++r]=i; } while(a[q_max[h_max+1]]-a[q_min[h_min+1]]>k) { ++j; if(q_max[h_max+1]==j) q_max[++h_max]=0; if(q_min[h_min+1]==j) q_min[++h_min]=0; } ans=max(ans,i-j); } cout<<ans<<endl; return 0; }
原文地址:http://blog.csdn.net/popoqqq/article/details/42916443