有关单调队列
想要理解算法,最有效的方式就是看例题了。
所以我们就看这道模板题
P1886 滑动窗口 /【模板】单调队列
刚开始我还不知道单调队列是个什么东西,但是大概知道要用一个双向的队列来写,于是就想到了multiset+queue。
我们首先把数字一个一个放到队列和multiset中,当我们发现队列的size等于k时,就可以将multiset中的第一个数和最后一个分别放到两个个记录数组中,一个是最小值一个是最大值,
然后二分找到muliset中队列的第一个数删去,再把队列第一个数pop掉就ok了,时间复杂度大概是nlogn。
然而这样的时间复杂度并不太行,t掉两个点只有80分,下面是代码。
#include<iostream> #include<set> #include<queue> using namespace std; multiset<int>q; queue<int> p; int minn[1000005], maxx[1000005], a = 0; int main() { int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) { int now; cin >> now; p.push(now); q.insert(now); if (p.size() == m) { a++; minn[a] = *q.begin(); auto b = q.end(); b--; maxx[a] = *b; b = q.lower_bound(p.front()); q.erase(b); p.pop(); } } for (int i = 1; i <= a; i++) cout << minn[i] << " "; cout << endl; for (int i = 1; i <= a; i++) cout << maxx[i] << " "; return 0; }
之后没有办法,就只好去学习了一下单调队列。
单调队列跟优先队列很像,都是队列中的元素要么单调递增要么单调递减,但是单调队列可以对两头进行操作。
由于stl当中没有单调队列,我们就只能手打(胡说明明有deque)。
对于这题来说,其实就是要我们维护一个大小为k的两个单调队列,一个单调递增,一个单调递减。
对于单调递增队列来说,我们只要遇到一个比队列中最后一个数还要小的数,那么我们就一直从队尾出队直到这个数比队尾的数大,并将其加入队列中。
而单调递增则相反不必赘述,下面直接上代码就好了。
#include<iostream> using namespace std; int a[1000005], q1[1000000], q2[1000005], n, k,book[1000005]; void maxx() { int tail = 0; int head = 1; for (int i = 1; i <= n; i++) { while (head <= tail && a[i] >= q2[tail])tail--; q2[++tail] = a[i]; book[tail] = i; while ( book[head] <= i - k) head++; if (i >= k)cout << q2[head] << " "; } } void minn() {//求窗口中最小的,其实是求一个单调递增队列,这样每次输出它的头部,那就必是最小的了 int tail = 0; int head = 1; for (int i = 1; i <= n; i++) { while (head <=tail && a[i] <= q1[tail])tail--;//遇到比队尾小的,我们就一直出队,直到大于队尾为止 q1[++tail] = a[i]; book[tail] = i; while (book[head] <= i - k) head++; if (i >= k)cout << q1[head] << " "; } cout << endl; } int main() { cin >> n >> k; for (int i = 1; i <= n; i++) cin >> a[i]; minn(); maxx(); return 0; }
我们这里采用了个手写队列。
手写队列时要将头节点初始化为1,尾节点初始化为0,具体为什么讲不清楚,但这样才能实现队列的操作。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix