题面
题意
多组数据
给n,k,m和n个数,问这n个数中最长满足其中最大值与最小值之差在m与k之间的子串的长度.
n<=100000
方法
因为n的范围和多组数据,必须用O(n)算法.
用单调队列来维护最大值和最小值,并据此dp
该单调队列使用时,将加入元素与队尾比较,根据维护的极值来判断比较规则,使队首表示的是该队列上一个pop的元素的位置右端到目前推入的元素的极值.
然后将两个队首作差,若大于k,则将两个队首中位置较前面的pop直至差小于等于k,此时满足条件的区间的左端点即为pop掉元素的位置的右边那个点.
再用此时的队首之差与l比较,若大于等于l,则更新答案.
注意,在操作中要时刻判断队列是否为空
代码
1.结构体
#include<bits/stdc++.h>
#define N 100010
using namespace std;
struct Dq
{
bool dx;
int id[N],nu[N],head,tail;
void init()
{
head=1;
tail=0;
}
void pop()
{
head++;
}
void push(int u,int v)
{
if(dx)
{
while(u>nu[tail]&&head<=tail) tail--;
}
else
{
while(u<nu[tail]&&head<=tail) tail--;
}
tail++;
id[tail]=v;
nu[tail]=u;
}
int frontn()
{
return nu[head];
}
int fronti()
{
return id[head];
}
int length()
{
return id[tail]-id[head]+1;
}
bool empty()
{
if(tail<head) return 1;
else return 0;
}
void print()
{
int i;
cout<<head<<" "<<tail<<endl;
for(i=head;i<=tail;i++)
{
cout<<nu[i]<<" ";
}
cout<<endl;
}
};
int n,l,r,num[N],ans;
Dq mn,mx;
int main()
{
int i,j;
mx.dx=1;
mn.dx=0;
while(~scanf("%d%d%d",&n,&l,&r))
{
int ll;
ll=0;
mx.init();
mn.init();
ans=0;
for(i=1;i<=n;i++)
{
scanf("%d",&num[i]);
mn.push(num[i],i);
mx.push(num[i],i);
while(!mx.empty()&&!mn.empty()&&mx.frontn()-mn.frontn()>r)
{
if(mx.fronti()>=mn.fronti()) ll=max(ll,mn.fronti()),mn.pop();
else ll=max(ll,mx.fronti()),mx.pop();
}
if(!mx.empty()&&!mn.empty()&&mx.frontn()-mn.frontn()>=l)
{
ans=max(ans,i-ll);
}
/*
cout<<"mx:";
mx.print();
cout<<"mn:";
mn.print();
// for(j=1;j<=500000000;j++);
//*/
}
if(r<l)
{
printf("0\n");
continue;
}
printf("%d\n",ans);
}
}
2.指针
#include<bits/stdc++.h>
#define N 1000005
#define max(a,b) (a>b?a:b)
using namespace std;
int a[N],ans,n,m,k,l,q1[N],q2[N],*b1,*b2,*e1,*e2;
int main()
{
for(;~scanf("%d %d %d",&n,&m,&k);)
{
ans=l=0;
e1=q1;e2=q2;b1=q1+1;b2=q2+1;
for(int i=1;i<=n;++i)
{
scanf("%d",a+i);
for(;!(b1>e1||*(a+i)<*(a+*e1));--e1);
for(;!(b2>e2||*(a+i)>*(a+*e2));--e2);
for(*(++e1)=*(++e2)=i;!(b1>e1||b2>e2)&&*(a+*b1)-*(a+*b2)>k;)
*b1>*b2?l=*(b2++):l=*(b1++);
if(!(b1>e1||b2>e2||*(a+*b1)-*(a+*b2)<m))
ans=max(ans,i-l);
}
printf("%d\n",ans);
}
return 0;
}