hdu 3530 Subsequence 最长的连续子序列,使得 M<=Max-Min<=K

Subsequence

http://acm.hdu.edu.cn/showproblem.php?pid=3530

 

 【 题意】:给出一个序列,求最长的连续子序列,使得 M<=Max-Min<=K
                n <= 10^5

 【思路】:单调队列可以快速知道i及之前的最大/小值。

           这里可以 枚举每个i为序列尾 ,并维护两个单调队列,一个存单调递减,一个存单调递增 

           如果2个队列的队头的差别大于m2,那么就通过减小大的(递减序列的fron2++),增大小的(递增序列的        front1++)来是dif更小,到底是front1++的还是front2++,应该哪个距离i最远(下标号较小)就哪个++,因为到时候我们要取的是距离i较小(下表好较大)的

  

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 
 5 using namespace std;
 6 int a[100010];
 7 int q[100010],qq[100010];//Max, Min
 8 
 9 int main()
10 {
11     int N,M,K;
12     while(~scanf("%d%d%d",&N,&M,&K))
13     {
14         for(int i=1;i<=N;i++)
15             scanf("%d",&a[i]);
16         int ans = 0;
17         int front1 = 0,tail1 = 0;
18         int front2 = 0,tail2 = 0;
19         int last1 = 0,last2 = 0;
20         for(int i=1;i<=N;i++)
21         {
22             //Max
23             while(front1<tail1 && a[qq[tail1-1]]<=a[i])tail1--;//  da
24             while(front2<tail2 && a[qq[tail2-1]]>=a[i])tail2--;//xiao
25             qq[tail2++] = q[tail1++] = i;
26             while(a[q[front1]]-a[qq[front2]] > K)
27             {
28                 if(q[front1]<qq[front2])
29                     last1 = q[front1++];   
30     /*需要先记录上一次的被淘汰的最值位置last ,这样[last+1,i]即为满足条件的连续子序列了
31       所以 前面 a[qq[tail1-1]]<=a[i] 而不是a[qq[tail1-1]]<a[i]  不然的话 last+1 的值可
32       能和last的只是一样的 同样不满足
33      长度为 i-(last+1)+1  即 i-ans   */
34                 else
35                     last2 = qq[front2++];
36                 /*   qq[]是单调递减的  front2++是减小最大值   q[]是单调递增的 front1++ 是增大最小值
37                 都可以使他们的dif减小  到底要减小哪个   应该哪个距离i最远就减小哪个*/
38             }
39             if(a[q[front1]]-a[qq[front2]]>=M)
40                 ans = max(ans,i-max(last1,last2));//取较大值
41         }
42         printf("%d\n",ans);
43     }
44     return 0;
45 }

 

posted @ 2013-12-17 11:21  galaxy77  阅读(237)  评论(0编辑  收藏  举报