这个deque,caiji整整看了俩小时,,,正所谓代码不长,句句皆精华,,
deque
双向队列,支持双向进入
典型例题
滑块问题
一个中心:
- 维护一个队列,这个队列是单调的。
两个基本点:
- 在一开始的时候,要判断长度与给定滑块长度的关系,如果超过了长度,则使队头出队
- 满足第一点后,与队尾进行比较,看看是不是满足单调。不满足则弹出队尾,然后再判断,使队中元素满足单调。
然后在插入该元素就行
//
// Created by Arc on 2021/1/28.
//
#include <iostream>
#include <queue>
using namespace std;
deque<int> q;
int a[10000];
int main()
{
int m,n;
cin>>n>>m;
for (int i = 0; i < n; ++i) {
cin>>a[i];
while(!q.empty()&&q.front()<i-m){//如果数量超标,则弹出对头
q.pop_front();
}
while(!q.empty()&&a[q.back()]>=a[i]){
/*如果要进入的数比队尾还小,队尾出列
* 一直比较到这个数可以满足单调
*/
q.pop_back();
}
q.push_back(a[i]);
cout<<q.front()<<" ";
}
}
最大子序列
题意
给你n个数,求出最大连续子段和,并且该子段长度不超过m,且不能为空子段。
思路
求完前缀和后,跟上面基本是一样的
#include <iostream>
using namespace std;
typedef long long ll;
int n,m,ans;
const int INF=0x3f3f3f3f;
const int maxn=300000+10;
int a[maxn],s[maxn];
deque<int> Q;
int main()
{
cin>>n>>m;
ans=-INF, s[0]=0;
Q.push_back(0);
for(int i=1;i<=n;i++)
{
cin>>a[i], s[i]=s[i-1]+a[i];
while(!Q.empty() && Q.front()<i-m)
Q.pop_front();
ans=max(ans,s[i]-s[Q.front()]);
while(!Q.empty() && s[Q.back()]>=s[i])
Q.pop_back();
Q.push_back(i);
}
cout<<ans<<endl;
}
小结
单调队列是一个思想,可以通过维护队列的单调性,来取某一段的maxmin,复杂度的话,每个数进出一次,为o(n)
参考博客:https://www.cnblogs.com/I-Love-You-520/p/13454305.html