您的位置:首页 > 其它

【单调队列】POJ2823-Sliding Window

2015-07-20 22:01 344 查看
单调队列经典题之一。

【思路】

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

【错误点】

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

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

#include<iostream>
#include<cstdio>
using namespace std;
const int MAXN=1000000+10;
int n,k,maxh,minh,maxt,mint;
int maxq[MAXN],minq[MAXN],num[MAXN];
int maxans[MAXN],minans[MAXN];

int main()
{
while (scanf("%d%d",&n,&k)!=EOF)
{
int maxhead=0,minhead=0,maxtail=0,mintail=0;
for (int i=0;i<n;i++)
{
/*删除下标超出范围的队首元素*/
if (maxhead<maxtail && maxq[maxhead]<=i-k) maxhead++;
if (minhead<mintail && minq[minhead]<=i-k) minhead++;

/*删除队尾元素*/
scanf("%d",&num[i]);
while (maxhead<maxtail && num[maxq[maxtail-1]]<=num[i]) maxtail--;maxtail++;
maxq[maxtail-1]=i;
while (minhead<mintail && num[minq[mintail-1]]>=num[i]) mintail--;mintail++;
minq[mintail-1]=i;
maxans[i]=num[maxq[maxhead]];
minans[i]=num[minq[minhead]];
}
for (int i=k-1;i<n;i++) cout<<minans[i]<<' ';cout<<endl;
for (int i=k-1;i<n;i++) cout<<maxans[i]<<' ';cout<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: