您的位置:首页 > 其它

NKOI 2152 滑动窗口

2016-04-16 11:04 281 查看
【单调队列】滑动窗口
Time Limit:10000MS  Memory Limit:65536K

Total Submit:232 Accepted:112
Case Time Limit:1000MS
Description
给你一个长度为N(N<=10^6)的数组,一个长为K的滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,找出窗体所包含的数字的最大和最小值,如下表所示:k的值为3

窗口位置                      最小值   最大值

[1  3  -1] -3  5  3  6  7       -1       3

1 [3  -1  -3] 5  3  6  7       -3       3

1  3 [-1  -3  5] 3  6  7       -3       5

1  3  -1 [-3  5  3] 6  7       -3       5

1  3  -1  -3 [5  3  6] 7        3       6

1  3  -1  -3  5 [3  6  7]       3       7

Input
第1行为n,k,第2行为长度为n的数组。

Output
共2行,第1行是每个位置的min value,第2行是每个位置的max value。

Sample Input
8 3
1 3 -1 -3 5 3 6 7

Sample Output
-1 -3 -3 -3 3 3
3 3 5 5 6 7

Source
poj 2823

可以构造一个递增序列和递减序列,当窗口滑动到一个新位置时,对于自增序列需要维护它的单调性,则如果新元素比队尾元素小队尾元素就出队列(因为没有存在的意义了)。然后判断队列首的元素是否还在窗口内,找到第一个在窗口内的就是满足条件的该窗口的最小数据。

对于窗口内的最大数据可以采用类似的处理方法。

以求窗口中最大值为例

此问题单调递减队列操作方法:

1.若队尾元素小于要加入的元素,

删除队尾元素,直到队尾元素不小

于新加入的元素或者队列为空

2.讨论队首元素的下标是否在窗口

范围以内,若不在,删除队首。

3.当前队首元素即是当前窗口的最大值

注意:可用二分法优化算法

假如当前入队元素为x;

   1.用二分法找出队列中比x大的第一个元素y;

   2.将队列中y以后的所有元素都从队列中删除;

   3.x入队;

注意:若找不到比x大的元素,则全部删除,然后x入队#include<cstdio>
#include<deque>
#include<iostream>
using namespace std;
inline void _read(int &xx){
char tt=getchar();bool asd=false;
while((tt<'0'||tt>'9')&&tt!='-')tt=getchar();
if(tt=='-')asd=true,tt=getchar();
for(xx=0;tt>='0'&&tt<='9';tt=getchar())xx=xx*10+(tt-'0');
if(asd==true)xx=0-xx;
}
struct wk{
int num;
int id;
};
deque<wk>bger;
deque<wk>smer;
int n,k,s[1000005];
int maxx[1000005],minn[1000005];
int cax=0,cit=0;
void push_bg(int x,int y){
wk temp;
temp.num=x;
temp.id=y;
bger.push_back(temp);
}
void push_sm(int x,int y){
wk temp;
temp.num=x;
temp.id=y;
smer.push_back(temp);
}
int main(){
_read(n);
_read(k);
int i,j;
for(i=1;i<=n;i++)_read(s[i]);
push_bg(s[1],1);
push_sm(s[1],1);
for(i=2;i<=k;i++){
while(!smer.empty()&&s[i]>=smer.back().num)smer.pop_back();
push_sm(s[i],i);
while(!bger.empty()&&s[i]<=bger.back().num)bger.pop_back();
push_bg(s[i],i);
}
maxx[++cax]=smer.front().num;
minn[++cit]=bger.front().num;
for(i=k+1;i<=n;i++){
while(!smer.empty()&&s[i]>=smer.back().num)smer.pop_back();
push_sm(s[i],i);
while(!bger.empty()&&s[i]<=bger.back().num)bger.pop_back();
push_bg(s[i],i);
while(smer.front().id<=i-k)smer.pop_front();
maxx[++cax]=smer.front().num;
while(bger.front().id<=i-k)bger.pop_front();
minn[++cit]=bger.front().num;
}
for(i=1;i<=cit;i++)printf("%d ",minn[i]);
printf("\n");
for(i=1;i<=cax;i++)printf("%d ",maxx[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: