HDU 3530
单调队列DP,开始想错了,WA了好多次。
后来才发现错在哪了。。
我们先枚举子串的结尾,并维护2个队列(单增,单减)。
如果2个队列的队头的差别大于k,则较小的队头值的位置肯定不满足要求。
那么就通过减小大的,增大小的来是dif更小。
直到找到一个合法位置now,那么对于i-1这个子串的结尾,now到i-1这个区间肯定满足要求。
所以有ans = max(ans,i-1-now+1)。
now初始值为-1,因为有可能最大长度为n。
View Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #define MAXN 100005 5 using namespace std; 6 int data[MAXN]; 7 8 int main() 9 { 10 int n,m,k; 11 while (scanf("%d%d%d",&n,&m,&k) != EOF) { 12 for (int i(0); i<n; ++i) { 13 scanf("%d",&data[i]); 14 } 15 int min_que[MAXN],max_que[MAXN]; 16 int min_front(-1),min_back(-1),max_front(-1),max_back(-1); 17 int ans = 0, now(-1); 18 for (int i(0); i<n; ++i) { 19 while (max_front != max_back && data[max_que[max_back]] <= data[i])--max_back; 20 while (min_front != min_back && data[min_que[min_back]] >= data[i])--min_back; 21 min_que[++min_back] = max_que[++max_back] = i; 22 while (min_front != min_back && max_front != max_back && 23 abs(data[min_que[min_front+1]] - data[max_que[max_front+1]]) > k) { 24 if (min_que[min_front+1] > max_que[max_front+1]) { 25 now = max_que[++max_front]; 26 } else { 27 now = min_que[++min_front]; 28 } 29 } 30 int dif = abs(data[min_que[min_front+1]] - data[max_que[max_front+1]]); 31 if (dif >= m) 32 ans = max(ans,i-now); 33 } 34 cout<<ans<<endl; 35 } 36 return 0; 37 }