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 }
posted on 2012-08-27 22:13  Dev-T  阅读(639)  评论(0编辑  收藏  举报