★实验任务
有一个长度为 n 的序列,第 i 个的数为 a[i]。我们定义如果它的一个连续的子串为“没有进行过干净的交易”,那么这个子串的最大值与最小值之差在[m,k]中。
现在,你的任务是找到一条最长的“没有进行过干净的交易”的子串。
★数据输入
第一行输入三个正整数 n m k (0<n<=10000),m(0 =< m =< k =< n)。
接下去一行有 n 个正整数,第 i 个数表示 a[i]的值。
★数据输出
输出一个数,表示这个子串的长度。
输入示例1
5 0 0
1 1 1 1 1
输出示例1
5
输入示例2
6 0 3
3 1 2 3 4 5
输出示例2
5
题解:
网上关于这道题只有
O
(
n
2
)
O(n^2)
O(n2)的暴力解法,事实上,用两个单调队列可在
O
(
n
)
O(n)
O(n)复杂度内解决。下面上代码:
#include<iostream>
using namespace std;
class Node{
public:
int pos,data;
Node(){}
Node(int pos,int data):pos(pos),data(data){}
Node(Node& other){
this->pos=other.pos;
this->data=other.data;
}
};
class Queue{
public:
int head,tail;
const int maxlen;
Node *queue;
Queue(int maxlen=(int)1e5+5):maxlen(maxlen){
this->head=0;
this->tail=0;
this->queue=new Node[maxlen];
}
~Queue(){
delete []this->queue;
}
bool empty(){
return this->head==this->tail;
}
int size(){
return (this->tail-this->head+this->maxlen)%this->maxlen;
}
Node& operator[](int index){
if(index<0){
return this->queue[(this->tail+index+this->maxlen)%this->maxlen];
}
else{
return this->queue[(this->head+index)%this->maxlen];
}
}
int append(Node& elem){
this->queue[this->tail]=elem;
this->tail=(this->tail+1)%this->maxlen;
return this->size();
}
Node& pop_left(){
Node &tmp=this->queue[this->head];
this->head=(this->head+1)%this->maxlen;
return tmp;
}
Node& pop(){
Node &tmp=this->queue[(this->tail-1+this->maxlen)%this->maxlen];
this->tail=(this->tail-1+this->maxlen)%this->maxlen;
return tmp;
}
friend ostream& operator<<(ostream& out,Queue& q);
};
ostream& operator<<(ostream& out,Queue& q){
for(int i=0;i<q.size();i++)
{
out<<q[i].data<<' ';
}
out<<endl;
return out;
}
int diff(Queue& maxq,Queue& minq){
return maxq.empty()||minq.empty()?0:maxq[0].data-minq[0].data;
}
int main(){
Queue maxq,minq;
int n,m,k,data[(int)1e5+5];
cin>>n>>m>>k;
int l=0,r=0,sub=0;
while(true){
//change sub
int tmp=diff(maxq,minq);
if(tmp<=k&&tmp>=m&&sub<r-l){
sub=r-l;
}
if(l==n-1)break;
//choose l++ or r++
if(tmp<=k&&r<=n-1){
cin>>data[r++];
Node elem(r-1,data[r-1]);
//minq
while(!minq.empty()&&minq[-1].data>data[r-1])minq.pop();
minq.append(elem);
//maxq
while(!maxq.empty()&&maxq[-1].data<data[r-1])maxq.pop();
maxq.append(elem);
}
else{
l++;
//minq
while(!minq.empty()&&minq[0].pos<l)minq.pop_left();
//maxq
while(!maxq.empty()&&maxq[0].pos<l)maxq.pop_left();
}
cout<<"-------l="<<l<<";r="<<r<<"--------"<<endl;
cout<<minq<<endl;
cout<<maxq<<endl;
}
cout<<sub;
return 0;
}