DP/单调队列优化
题解:http://www.cnblogs.com/yymore/archive/2011/06/22/2087553.html
引用:
首先我们要明确几件事情
1.假设我们现在知道序列(i,j)是符合标准的,那么如果第j+1个元素不比(i,j)最大值大也不比最小值小,那么(i,j+1)也是合法的
2.如果(i,j)不合法的原因是差值比要求小,那在(i,j)范围内的改动是无效的,需要加入j+1元素充当最大值或者最小值才可能获得合法的序列
3.假设序列(i,j)的差值比要求大,那么我们必须将其中的最大值或者最小值从序列中删除出去,才可能获得一个合法的序列,只往里加入元素是不可能令序列合法的
//HDOJ 3530
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
#define CC(a,b) memset(a,b,sizeof(a))
using namespace std;
int getint(){
int v=,sign=; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') sign=-; ch=getchar();}
while(isdigit(ch)) {v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=1e6+,INF=~0u>>;
const double eps=1e-;
/*******************template********************/ deque<int>mx,mn;
int a[N];
int main(){
#ifndef ONLINE_JUDGE
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif
int n,m,k;
while(scanf("%d%d%d",&n,&m,&k)!=EOF){
int start=,ans=;
F(i,,n) a[i]=getint();
mx.clear(); mn.clear();
F(i,,n){
while(!mx.empty() && a[mx.back()]<=a[i]) mx.pop_back();
while(!mn.empty() && a[mn.back()]>=a[i]) mn.pop_back();
mx.pb(i); mn.pb(i);
while(a[mx.front()]-a[mn.front()]>k){
if (mx.front()<mn.front()){
start=mx.front();
mx.pop_front();
}else{
start=mn.front();
mn.pop_front();
}
}
if (a[mx.front()]-a[mn.front()]>=m)
ans=max(i-start,ans);
}
printf("%d\n",ans);
}
return ;
}