分类 :裸单调队列
传送门:滑动窗口
思路:
单调队列,就是字面意思。
如何维护? (假设我们是单调减的队列)
维护时,保证所有元素最多进队一次出队一次,复杂度O(n)
我们在队头放最大的元素<id,val>,向右依次递减。
在队尾插入新元素时,检查新元素是否比队尾元素大:是,则删除队尾元素,直到 比队尾元素小时,插入新元素在队尾。
同时还要检查一下,是否还在窗口范围内
AC代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
typedef pair<int,int> p;
p single_q[maxn];
int head=1,tail=0;
int n,m,a[maxn];//题目数据
void push_singleQueue2(p now)//单调队列(减)
{
while( head<=tail && single_q[tail].second<=now.second )
tail--;
single_q[++tail]=now;
while(single_q[head].first<=now.first-m)
head++;
if(now.first>=m) printf("%d ", single_q[head].second);
}
void push_singleQueue(p now)//单调队列(增)
{
while( head<=tail && single_q[tail].second>=now.second )
tail--;
single_q[++tail]=now;
while(single_q[head].first<=now.first-m)
head++;
if(now.first>=m) printf("%d ", single_q[head].second);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
push_singleQueue(p(i,a[i]));
}
puts("");
head=1,tail=0;
for(int i=1;i<=n;i++)
push_singleQueue2(p(i,a[i]));
puts("");
}