014.单调队列
区分优先队列
它们都有 O( 1 ) 的最值访问
c++标准库中就有priority_queue(优先队列)
而优先队列需要我们手动实现
优先队列priority_queue
- 二叉堆
- O ( logn ) 的插入,删除
- 维护 全局 动态最值
优先队列
- 双端队列 / 静态数组
- O ( 1 ) 的插入、删除
- 维护 滑动窗口 最值
实现方法
现有一个数组 nums[ ] , 窗口大小为 k ,我们需要获得每个窗口的最大值
静态数组
效率高
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
丑陋地解决一系列区间最值问题
其实是水模板
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;
}
};
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;
}
};
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;
}
};
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];
}
};
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;
}
};
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();
}
}
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();
}
}
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();
}
}
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();
}
}

浙公网安备 33010602011771号