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 ",ans); 43 } 44 return 0; 45 }