poj 2823 Sliding Window
给出n个数 分别求出连续的k个数中的最小值 最大值
如果单纯的用循环来遍历 然后用优先队列存储 取出最小值最大值 那么会超时。。。
然后这里就有一个叫单调数列的东西
用递减队列 队首 来存储区间内的最大值 首先是从前k个中找出递减的队列 队首就是最大值
然后 在后面n-k个数中进行遍历 首先要判断 当前存储的最大值是不是在这个范围中 不在就往后推
因为存储递减队列是从前往后扫的 只要后面有比前面大的 队尾的数就不在了。。
意思就是位置在前面的 但是比后面小的数 就会被删除了 所以队列中后面的数比前面的数小 且序号比前面存储的大
递增队列类似 不再赘述
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <queue>
#define eps 1e-8
#define op operator
#define MOD 10009
#define MAXN 1000010
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define FOV(i,a,b) for(int i=a;i>=b;i--)
#define REP(i,a,b) for(int i=a;i<b;i++)
#define REV(i,a,b) for(int i=a-1;i>=b;i--)
#define MEM(a,x) memset(a,x,sizeof a)
#define ll __int64
using namespace std;
struct node
{
int val;//值
int order;//序号
};
node no[MAXN];
int a[MAXN];
int mi[MAXN];
int mx[MAXN];
int main()
{
//freopen("ceshi.txt","r",stdin);
int n,k;
while(scanf("%d%d",&n,&k)!=EOF)
{
for(int p=0;p<n;p++)
scanf("%d",&a[p]);
int head,tail,i,j,idx;
head=0; tail=-1; i=0; j=-1;//维护递减的队列 i j 分别是队首和队尾元素原来的下标
idx=0;
for(int p=0;p<k;p++)
{
while(head<=tail&&no[tail].val<a[p]) tail--;
no[++tail].val=a[p]; no[tail].order=++j;
}
mx[idx++]=no[head].val;
for(int p=k;p<n;p++)
{
if(no[head].order==i) head++;
i++;
while(head<=tail&&no[tail].val<a[p]) tail--;
no[++tail].val=a[p]; no[tail].order=++j;
mx[idx++]=no[head].val;
}
head=0; tail=-1; i=0; j=-1;
idx=0;
for(int p=0;p<k;p++)
{
while(head<=tail&&no[tail].val>a[p]) tail--;
no[++tail].val=a[p]; no[tail].order=++j;
}
mi[idx++]=no[head].val;
for(int p=k;p<n;p++)
{
if(no[head].order==i) head++;
i++;
while(head<=tail&&no[tail].val>a[p]) tail--;
no[++tail].val=a[p]; no[tail].order=++j;
mi[idx++]=no[head].val;
}
printf("%d",mi[0]);
for(int i=1;i<=(n-k);i++)
printf(" %d",mi[i]);
puts("");
printf("%d",mx[0]);
for(int i=1;i<=(n-k);i++)
printf(" %d",mx[i]);
puts("");
}
return 0;
}