【单调队列】POJ2823-Sliding Window

单调队列经典题之一。

【思路】

设置两个单调队列分别记录最大值和最小值。对于每一个新读入的数字,进行两次操作(对于求最大值和最小值中的某一个而言),一是若队首不在滑窗范围内则删去;二是删去队末比当前值小(或大)的值,并将当前值插入对尾。每一次的最小(大)值就是当前单调队列的队首。

【错误点】

一定要写while (scanf("%d%d",&n,&k)!=EOF),否则会WA。

我一开始的做法是这样的:先把第一个数插入队尾,再从第二个数开始进行后续操作。这样的问题在于如果滑窗大小为1,则第一个数无法被输出就出队,导致WA。故一定要先设置一个空队列,再逐一插入。

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int MAXN=1000000+10;
 5 int n,k,maxh,minh,maxt,mint;
 6 int maxq[MAXN],minq[MAXN],num[MAXN];
 7 int maxans[MAXN],minans[MAXN];
 8
 9 int main()
10 {
11     while (scanf("%d%d",&n,&k)!=EOF)
12     {
13         int maxhead=0,minhead=0,maxtail=0,mintail=0;
14         for (int i=0;i<n;i++)
15         {
16             /*删除下标超出范围的队首元素*/
17             if (maxhead<maxtail && maxq[maxhead]<=i-k) maxhead++;
18             if (minhead<mintail && minq[minhead]<=i-k) minhead++;
19
20
21             /*删除队尾元素*/
22             scanf("%d",&num[i]);
23             while (maxhead<maxtail && num[maxq[maxtail-1]]<=num[i]) maxtail--;maxtail++;
24             maxq[maxtail-1]=i;
25             while (minhead<mintail && num[minq[mintail-1]]>=num[i]) mintail--;mintail++;
26             minq[mintail-1]=i;
27             maxans[i]=num[maxq[maxhead]];
28             minans[i]=num[minq[minhead]];
29         }
30         for (int i=k-1;i<n;i++) cout<<minans[i]<<‘ ‘;cout<<endl;
31         for (int i=k-1;i<n;i++) cout<<maxans[i]<<‘ ‘;cout<<endl;
32     }
33     return 0;
34 }
时间: 2024-10-06 00:31:43

【单调队列】POJ2823-Sliding Window的相关文章

POJ2823 Sliding Window (单调队列)

POJ2823 Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 38342   Accepted: 11359 Case Time Limit: 5000MS Description An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the ve

ACM-单调队列之Sliding Window——poj2823

Sliding Window Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 36326   Accepted: 10762 Case Time Limit: 5000MS Description An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left

POJ2823 Sliding Window【双端队列】

求连续的k个中最大最小值,k是滑动的,每次滑动一个 用双端队列维护可能的答案值 如果要求最小值,则维护一个单调递增的序列 对一开始的前k个,新加入的如果比队尾的小,则弹出队尾的,直到新加入的比队尾大,加入队尾 从第k+1个到最后一个,按照上述规则,压入新数,然后弹出队首元素(满足队首元素对应原来序列的位置必须在视窗内,否则,继续弹出下一个) #include <cstdio> #include <cstdlib> #include <iostream> #include

POJ2823 Sliding Window(单调队列)

单调队列,我用deque维护.这道题不难写,我第二次写单调队列,1次AC. ----------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<deque> #define rep(i,r) for(int i=0;i<r;i++) #define clr(x,c) memset

POJ2823 Sliding Window (单调队列的基本应用)

题目链接: http://poj.org/problem?id=2823 题意: 给定一个长度为n的序列,求每个长度为k的区间的最大值与最小值 分析: 单调队列的基本应用 代码如下: <span style="font-size:14px;">#include <iostream> #include <cstring> #include <cstdio> #include <queue> #include <vector

POJ2823 Sliding Window

Time Limit: 12000MS   Memory Limit: 65536K Total Submissions: 53086   Accepted: 15227 Case Time Limit: 5000MS Description An array of size n ≤ 106 is given to you. There is a sliding window of size k which is moving from the very left of the array to

单调队列 poj2823,fzu1894

题目链接:http://poj.org/problem?id=2823 用RMQ超时了,我想应该是不会的,看discuss说,之前RMQ过了. 维护两个单调队列. 单调递减的队列,每插入一个时: 超过单调队列长度,左移头指针. 第一个或者符合条件,直接加到后面. 否则,一直退: 1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 6 u

POJ2823.Sliding Window——单调队列

http://poj.org/problem?id=2823 求长度为k的子序列里面的最大值,最小值 #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <algorithm> #define pk push_back const int INF = 0x3f3f3f3f; const int maxn = 1000010; usi

学习笔记:单调队列

转自:http://apps.hi.baidu.com/share/detail/34010558 [单调队列]在解一个序列某个区间段的最值问题,我们可以用到单调队列来解决.  比如poj2823 Sliding Window 就是一个很好的例子:给定一个序列,要求序列中固定长度为k 的区间中的最大值和最小值.  [原理]单调队列维护的是区间最值:  1.最大值的维护:          比如我们要维护一个区间为k的最大值的单调队列,由于新插入 的节点他的“生命力”肯定比原先已经在队列中的元素“