014.单调队列

区分优先队列

它们都有 O( 1 ) 的最值访问

c++标准库中就有priority_queue(优先队列)

而优先队列需要我们手动实现

优先队列priority_queue

  • 二叉堆
  • O ( logn ) 的插入,删除
  • 维护 全局 动态最值

优先队列

  • 双端队列 / 静态数组
  • O ( 1 ) 的插入、删除
  • 维护 滑动窗口 最值

实现方法

现有一个数组 nums[ ] , 窗口大小为 k ,我们需要获得每个窗口的最大值

leetcode239

静态数组

效率高

vector<int>ans;//存储每个窗口的最大值
int n = nums.size();
int q [ n ] // 存储下标
int h=0,t=-1;//头,尾
for(int i=0;i<(int)nums.size();++i){
    while(t>=h&&nums[q[t]]<nums[i]){
        t--;
    }
    q[++t]=i;
    if(i+1>=k){
        while(t>=h&&i-q[h]+1>k){
            h++;
        }
        ans.push_back(nums[q[h]]);
    }
}

动态双端队列

更直观?

int n=nums.size();
vector<int>ans;
deque<int>q;
for(int i=0;i<n;i++){
    while(!q.empty()&&q.back()<nums[i]){
        q.pop_back();
    }
    q.push_back(nums[i]);
    if(i+1>=k){
        ans.push_back(q.front());
        if(nums[i-k+1]==q.front()){
            q.pop_front();
        }
    }
}

以上是最大值,最小值同理

封装

显著慢于静态实现
int q [ n ] , h=0 , t=-1

#include<deque>
#include<cassert>
using namespace std;
template<typename T>class MonotonicQueue{
    deque<T>q,m,M;
    public:
    void push(T e){
        q.push_back(e);
        while(!m.empty()&&m.back()>e)m.pop_back();
        m.push_back(e);
        while(!M.empty()&&M.back()<e)M.pop_back();
        M.push_back(e);
    }
    T max(){return M.front();}
    T min(){return m.front();}
    T pop(){
        T x=q.front();
        q.pop_front();
        if(x==m.front())m.pop_front();
        if(x==M.front())M.pop_front();
        return x;
    }
    int size()const{return q.size();}
    bool empty()const{return q.size()==0;}
};

习题

可以使用上面的MonotonicQueue

丑陋地解决一系列区间最值问题

其实是水模板

leetcode 239

code 1
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int>ans;
        int n=nums.size();
        int q[100005];
        int h=0,t=-1;
        for(int i=0;i<n;++i){
            while(h<=t&&nums[q[t]]<nums[i])t--;
            q[++t]=i;
            if(i+1>=k){
            while(h<=t&&q[h]<i-k+1)h++;
            ans.push_back(nums[q[h]]);
            }
        }
        return ans;
    }
};
code 2
class Solution {
    template<typename T>
    class MonotonicQueue{
    deque<T>q,m,M;
    public:
    void push(T e){
        q.push_back(e);
        while(!m.empty()&&m.back()>e)m.pop_back();
        m.push_back(e);
        while(!M.empty()&&M.back()<e)M.pop_back();
        M.push_back(e);
    }
    T max(){return M.front();}
    T min(){return m.front();}
    T pop(){
        T x=q.front();
        q.pop_front();
        if(x==m.front())m.pop_front();
        if(x==M.front())M.pop_front();
        return x;
    }
    int size()const{return q.size();}
    bool empty()const{return q.size()==0;};
};
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int>ans;
        MonotonicQueue<int>q;
        for(int i=0;i<(int)nums.size();++i){
            q.push(nums[i]);
            if(i+1>=k){
                ans.push_back(q.max());
                q.pop();
            }
        }
        return ans;
    }
};

leetcode 1438

code 1
class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        int n=nums.size();
        vector<int>q1(100005),q2(100005);
        int h1=0,t1=-1,h2=0,t2=-1;
        int l=0,r=0,ans=0;
        while(r<n){
            while(t1>=h1&&nums[q1[t1]]<nums[r])t1--;
            q1[++t1]=r;
            while(t2>=h2&&nums[q2[t2]]>nums[r])t2--;
            q2[++t2]=r;
            r++;
            while(h1<=t1&&q1[h1]<l)h1++;
            while(h2<=t2&&q2[h2]<l)h2++;
            while(l<r&&nums[q1[h1]]-nums[q2[h2]]>limit){
                l++;
                while(h1<=t1&&q1[h1]<l)h1++;
                while(h2<=t2&&q2[h2]<l)h2++;
            }
            if(r-l>ans)ans=r-l;
        }
        return ans;
    }
};
code 2
class Solution {
    template<typename T>class MonotonicQueue{
    deque<T>q,m,M;
    public:
    void push(T e){
        q.push_back(e);
        while(!m.empty()&&m.back()>e)m.pop_back();
        m.push_back(e);
        while(!M.empty()&&M.back()<e)M.pop_back();
        M.push_back(e);
    }
    T max(){return M.front();}
    T min(){return m.front();}
    T pop(){
        T x=q.front();
        q.pop_front();
        if(x==m.front())m.pop_front();
        if(x==M.front())M.pop_front();
        return x;
    }
    int size()const{return q.size();}
    bool empty()const{return q.size()==0;}
};
public:
    int longestSubarray(vector<int>& nums, int limit) {
        int n=nums.size();
        MonotonicQueue<int>q;
        int ans=0;
        for(int i=0;i<n;i++){
            q.push(nums[i]);
            while(!q.empty()&&q.max()-q.min()>limit)q.pop();
            ans=max(ans,q.size());
        }
        return ans;
    }
};

leetcode 862

code 2
class Solution {
    template<typename T>class MonotonicQueue{
    deque<T>q,m,M;
    public:
    void push(T e){
        q.push_back(e);
        while(!m.empty()&&m.back()>e)m.pop_back();
        m.push_back(e);
        while(!M.empty()&&M.back()<e)M.pop_back();
        M.push_back(e);
    }
    T max(){return M.front();}
    T min(){return m.front();}
    T pop(){
        T x=q.front();
        q.pop_front();
        if(x==m.front())m.pop_front();
        if(x==M.front())M.pop_front();
        return x;
    }
    int size()const{return q.size();}
    bool empty()const{return q.size()==0;}
};
public:
    int shortestSubarray(vector<int>& nums, int k) {
        int n=nums.size();
        vector<long>pre(n+1,0);
        for(int i=0;i<n;++i)pre[i+1]=pre[i]+nums[i];
        MonotonicQueue<long>window;
        int l=0,r=0;
        int ans=INT_MAX;
        while(r<=n){
            window.push(pre[r++]);
            while(r<=n&&!window.empty()&&pre[r]-window.min()>=k){
                ans=min(ans,r-l);
                window.pop();
                l++;
            }
        }
        return ans==INT_MAX?-1:ans;
    }
};

leetcode 1696

code 1
class Solution {
public:
    int maxResult(vector<int>& nums, int k) {
        int n=nums.size();
        vector<int>q(n);
        int h=0,t=-1;
        vector<int>dp(n);
        dp[0]=nums[0];
        q[++t]=0;
        for(int i=1;i<n;++i){
            while(t>=h&&i-q[h]>k)h++;
            dp[i]=nums[i]+dp[q[h]];
            while(t>=h&&dp[q[t]]<dp[i])t--;
            q[++t]=i;
        }
        return dp[n-1];
    }
};
code 2
class Solution {
    template<typename T>class MonotonicQueue{
    deque<T>q,m,M;
    public:
    void push(T e){
        q.push_back(e);
        while(!m.empty()&&m.back()>e)m.pop_back();
        m.push_back(e);
        while(!M.empty()&&M.back()<e)M.pop_back();
        M.push_back(e);
    }
    T max(){return M.front();}
    T min(){return m.front();}
    T pop(){
        T x=q.front();
        q.pop_front();
        if(x==m.front())m.pop_front();
        if(x==M.front())M.pop_front();
        return x;
    }
    int size()const{return q.size();}
    bool empty()const{return q.size()==0;}
};
public:
    int maxResult(vector<int>& nums, int k) {
        int n=nums.size();
        vector<int>dp(n);
        dp[0]=nums[0];
        MonotonicQueue<int>q;
        q.push(dp[0]);
        for(int i=1;i<n;++i){
            dp[i]=nums[i]+q.max();
            if(q.size()>=k)q.pop();
            q.push(dp[i]);
        }
        return dp[n-1];
    }
};

leetcode 1425

code 1
class Solution {
public:
    int constrainedSubsetSum(vector<int>& nums, int k) {
        int n=nums.size();
        vector<int>q(n);
        int h=0,t=-1;
        vector<int>dp(n);
        dp[0]=nums[0];
        q[++t]=0;
        for(int i=1;i<n;i++){
            while(t>=h&&i-q[h]>k)h++;
            dp[i]=max(nums[i],dp[q[h]]+nums[i]);
            while(t>=h&&dp[q[t]]<dp[i])t--;
            q[++t]=i;
        }
        int ans=dp[0];
        for(int x:dp)if(x>ans)ans=x;
        return ans;
    }
};
code 2
class Solution {
    template<typename T>class MonotonicQueue{
    deque<T>q,m,M;
    public:
    void push(T e){
        q.push_back(e);
        while(!m.empty()&&m.back()>e)m.pop_back();
        m.push_back(e);
        while(!M.empty()&&M.back()<e)M.pop_back();
        M.push_back(e);
    }
    T max(){return M.front();}
    T min(){return m.front();}
    T pop(){
        T x=q.front();
        q.pop_front();
        if(x==m.front())m.pop_front();
        if(x==M.front())M.pop_front();
        return x;
    }
    int size()const{return q.size();}
    bool empty()const{return q.size()==0;}
};
public:
    int constrainedSubsetSum(vector<int>& nums, int k) {
        int n=nums.size();
        vector<int>dp(n);
        dp[0]=nums[0];
        MonotonicQueue<int>q;
        q.push(dp[0]);
        for(int i=1;i<n;i++){
            dp[i]=max(nums[i],q.max()+nums[i]);
            if(q.size()>=k)q.pop();
            q.push(dp[i]);
        }
        int ans=dp[0];
        for(int x:dp)if(x>ans)ans=x;
        return ans;
    }
};

luogu P1886

code
#include<bits/stdc++.h>
using namespace std;
namespace IO{template<typename T>void read(T&x){x=0;bool f=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}if(f)x=-x;}void read(char&c){c=getchar();while(isspace(c))c=getchar();}void read(string&s){s.clear();char ch=getchar();while(isspace(ch))ch=getchar();while(!isspace(ch)&&ch!=EOF){s+=ch;ch=getchar();}}template<typename T,typename...Args>void read(T&first,Args&...rest){read(first);read(rest...);}template<typename T>void wr(T x){if(x==0){putchar('0');return;}if(x<0){putchar('-');x=-x;}char stk[20];int top=0;while(x){stk[++top]=x%10+'0';x/=10;}while(top){putchar(stk[top--]);}}void wr(const char c){putchar(c);}void wr(const string&s){for(char c:s)putchar(c);}void wr(const char*s){while(*s)putchar(*s++);}template<typename T>void wr(const T&x,char sep){wr(x);putchar(sep);}template<typename T,typename...Args>void wr(const T&first,const Args&...rest){wr(first);((putchar(' '),wr(rest)),...);}}using namespace IO;
typedef long long ll;
typedef pair<int,int> pii;
template<typename T>class MonotonicQueue{
    deque<T>q,m,M;
    public:
    void push(T e){
        q.push_back(e);
        while(!m.empty()&&m.back()>e)m.pop_back();
        m.push_back(e);
        while(!M.empty()&&M.back()<e)M.pop_back();
        M.push_back(e);
    }
    T max(){return M.front();}
    T min(){return m.front();}
    T pop(){
        T x=q.front();
        q.pop_front();
        if(x==m.front())m.pop_front();
        if(x==M.front())M.pop_front();
        return x;
    }
    int size()const{return q.size();}
    bool empty()const{return q.size()==0;}
};
void solve(){
    int n,k;
    read(n,k);
    MonotonicQueue<int>q;
    vector<int>a(n),m,M;
    for(int i=0;i<n;++i)read(a[i]);
    for(int i=0;i<n;++i){
        q.push(a[i]);
        if(i+1>=k){
            m.push_back(q.min());
            M.push_back(q.max());
            q.pop();
        }
    }
    int siz=m.size();
    for(int i=0;i<siz;i++){
        wr(m[i]);
        if(i==siz-1)wr('\n');
        else wr(' ');
    }
    for(int i=0;i<siz;i++){
        wr(M[i]);
        if(i==siz-1)wr('\n');
        else wr(' ');
    }
}
int main(){
    int T=1;
    //read(T);
    while(T--){
        solve();
    }
}

luogu P2032

code
#include<bits/stdc++.h>
using namespace std;
namespace IO{template<typename T>void read(T&x){x=0;bool f=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}if(f)x=-x;}void read(char&c){c=getchar();while(isspace(c))c=getchar();}void read(string&s){s.clear();char ch=getchar();while(isspace(ch))ch=getchar();while(!isspace(ch)&&ch!=EOF){s+=ch;ch=getchar();}}template<typename T,typename...Args>void read(T&first,Args&...rest){read(first);read(rest...);}template<typename T>void wr(T x){if(x==0){putchar('0');return;}if(x<0){putchar('-');x=-x;}char stk[20];int top=0;while(x){stk[++top]=x%10+'0';x/=10;}while(top){putchar(stk[top--]);}}void wr(const char c){putchar(c);}void wr(const string&s){for(char c:s)putchar(c);}void wr(const char*s){while(*s)putchar(*s++);}template<typename T>void wr(const T&x,char sep){wr(x);putchar(sep);}template<typename T,typename...Args>void wr(const T&first,const Args&...rest){wr(first);((putchar(' '),wr(rest)),...);}}using namespace IO;
typedef long long ll;
typedef pair<int,int> pii;
template<typename T>class MonotonicQueue{
    deque<T>q,m,M;
    public:
    void push(T e){
        q.push_back(e);
        while(!m.empty()&&m.back()>e)m.pop_back();
        m.push_back(e);
        while(!M.empty()&&M.back()<e)M.pop_back();
        M.push_back(e);
    }
    T max(){return M.front();}
    T min(){return m.front();}
    T pop(){
        T x=q.front();
        q.pop_front();
        if(x==m.front())m.pop_front();
        if(x==M.front())M.pop_front();
        return x;
    }
    int size()const{return q.size();}
    bool empty()const{return q.size()==0;}
};
void solve(){
    int n,k;
    read(n,k);
    MonotonicQueue<ll>q;
    vector<ll>a(n);
    for(int i=0;i<n;++i)read(a[i]);
    for(int i=0;i<n;++i){
        q.push(a[i]);
        if(i+1>=k){
            wr(q.max(),'\n');
            q.pop();
        }
    }
}
int main(){
    int T=1;
    //read(T);
    while(T--){
        solve();
    }
}

luogu P2251

code
#include<bits/stdc++.h>
using namespace std;
namespace IO{template<typename T>void read(T&x){x=0;bool f=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}if(f)x=-x;}void read(char&c){c=getchar();while(isspace(c))c=getchar();}void read(string&s){s.clear();char ch=getchar();while(isspace(ch))ch=getchar();while(!isspace(ch)&&ch!=EOF){s+=ch;ch=getchar();}}template<typename T,typename...Args>void read(T&first,Args&...rest){read(first);read(rest...);}template<typename T>void wr(T x){if(x==0){putchar('0');return;}if(x<0){putchar('-');x=-x;}char stk[20];int top=0;while(x){stk[++top]=x%10+'0';x/=10;}while(top){putchar(stk[top--]);}}void wr(const char c){putchar(c);}void wr(const string&s){for(char c:s)putchar(c);}void wr(const char*s){while(*s)putchar(*s++);}template<typename T>void wr(const T&x,char sep){wr(x);putchar(sep);}template<typename T,typename...Args>void wr(const T&first,const Args&...rest){wr(first);((putchar(' '),wr(rest)),...);}}using namespace IO;
typedef long long ll;
typedef pair<int,int> pii;
template<typename T>class MonotonicQueue{
    deque<T>q,m,M;
    public:
    void push(T e){
        q.push_back(e);
        while(!m.empty()&&m.back()>e)m.pop_back();
        m.push_back(e);
        while(!M.empty()&&M.back()<e)M.pop_back();
        M.push_back(e);
    }
    T max(){return M.front();}
    T min(){return m.front();}
    T pop(){
        T x=q.front();
        q.pop_front();
        if(x==m.front())m.pop_front();
        if(x==M.front())M.pop_front();
        return x;
    }
    int size()const{return q.size();}
    bool empty()const{return q.size()==0;}
};
void solve(){
    int n,k;
    read(n,k);
    MonotonicQueue<ll>q;
    vector<ll>a(n);
    for(int i=0;i<n;++i)read(a[i]);
    for(int i=0;i<n;++i){
        q.push(a[i]);
        if(i+1>=k){
        wr(q.min(),'\n');
            q.pop();
        }
    }
}
int main(){
    int T=1;
    //read(T);
    while(T--){
        solve();
    }
}

bzoj 5424

code
#include<bits/stdc++.h>
using namespace std;
#define ll  long long
#define pii pair<int,int>
#define MOD 1000000007
#define INF 0x3f3f3f3f
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
const int MAXN=100005;
int a[MAXN],s[MAXN];
int f[MAXN],g[MAXN];
pii q[MAXN];
int h,t,cur;
void solve(){
    int n=read(),m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    n++;
    s[0]=0;
    for(int i=1;i<=n;i++){
        s[i]=s[i-1]+a[i];
        f[i]=INF;
        g[i]=s[i];
    }
    f[0]=0;
    int ans=INF;
    int cnt=1;
    for(int j=1;j<=305;j++){
        h=0,t=1;
        cur=0;
        q[++h]={0,0};
        int Min=INF;
        for(int i=1;i<=n;i++){
            while(s[i-1]-s[cur]>m){
                Min=min(Min,g[cur]-s[cur]);
                cur++;
            }
            int temp=f[i];
            f[i]=s[i-1]+Min;
            while(q[h].second<cur)h++;
            f[i]=min(f[i],q[h].first);
            while(h<=t&&q[t].first>temp)t--;
            q[++t]={temp,i};
            f[i]+=a[i]*cnt;
        }
        ans=min(ans,f[n]);
        memcpy(g,f,sizeof(g));
        cnt++;
    }
    printf("%d\n",ans);
}
signed main(){
    int Case_num=read();
    while(Case_num--){
        solve();
    }
}
posted @ 2025-12-18 18:55  射杀百头  阅读(4)  评论(0)    收藏  举报