BZOJ 2096

【分析】
这道题就TM是个坑
给一段序列,求一段最长子序列,使序列中最大值-最小值<=k
分别用两个递增和递减的队列维护。枚举右端点,根据条件不断删除左端点,然后取min。
fffff**k

【代码】

#include<iostream>
#include<cstdio>
#include<algorithm>
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int T=3000005;
int n,k,l1,r1,l2,r2,ans,t=1,a[T],q1[T],q2[T];
int main()
{
int i;
scanf("%d%d",&k,&n);
fo(i,1,n) scanf("%d", &a[i]);
fo(i,1,n)
{
while(l1<r1 && a[i]<=a[q1[r1-1]]) r1--;
while(l2<r2 && a[i]>=a[q2[r2-1]]) r2--;
q1[r1++]=q2[r2++] = i;
while(a[q2[l2]]-a[q1[l1]]>k)
if(q2[l2]>q1[l1]) t=q1[l1]+1,l1++;
else t=q2[l2]+1,l2++;
ans=max(ans,i-t+1);
}
printf("%d\n",ans);
return 0;
}