单调队列

滑动窗口,求多段区间的最大最小值

考虑当 [l,r] 变为 [l+1,r+1] 时要做的事

  • 第 l 个元素(如果有)不再做贡献了,将他弹出队列

  • 将第 r+1 个元素加入。若此时队列顶的元素 x 比 r+1 小,说明 r+1 永远比 x 更优(x 比 r+1 先退役,不会出现一个区间有 x 而没有 r+1 )

  • 更新 [l+1,r+1] 的最大值

代码

// 不要学我用双端队列
// 自己手写队列常数小
int k , n , a[maxn];
void workmax(){
    deque<int> q;
    fo(i,1,k-1){
        while(!q.empty() and a[q.back()] < a[i]) q.pop_back();
        q.push_back(i);
    }
    fo(i,k,n){
        int st = i-k+1;
        while(!q.empty() and q.front() < st) q.pop_front();
        while(!q.empty() and a[q.back()] < a[i]) q.pop_back();
        q.push_back(i);
        printf("%d ",a[q.front()]);
    }
    puts("");
}