介绍
常常被用来解决互不包含的最值问题。什么是互不包含的区间?[1, 5]包含[2, 3],但不包含[1, 3]或者[3, 4]。时间复杂度为,即数组长度加询问次数。
代码介绍
以P1886为例。对于原数组a,创建一个新的数组q,并在q上形成单调队列,以b和f来表示单调队列的开头和结尾。
int n,k;
int a[1000005], q[1000005];
int main(int argc, const char argv[]){
cin>>n>>k;
for(int i = 0; i<n; i++){
cin>>a[i];
}
int f = 0;
int b = 0;
return 0;
}
接下来每次在a数组中读入一个数字,都需要更新单调队列。如果是要求最小值,则需使单调队列为严格递增。对于队尾来说,如果有比新读入的数小的数,则需要删去那些数,再把读入的数排到末尾。对于队首来说,如果已经没有用了,不在题目询问的区间之中,也需要删去。
for(int i = 0; i<n; i++){
while(b < f && a[i] <= a[q[f-1]]){
f--;
}//删去队尾的数
q[f++] = i;//加入队尾
while(i-k >= q[b]){
b++;
}//删去队首过时的数
if(i >= k-1){
cout<<a[q[b]];
if(i == n-1){
cout<<endl;
}
else{
cout<<" ";
}
}
}
注意,单调队列中存储的是下标,并且队列可以没有重复的数字。