Time Limit: 12000MS   Memory Limit: 65536K
Total Submissions: 58002   Accepted: 16616
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 the very right. You can only see the k numbers in the window. Each time the sliding window moves rightwards by one position. Following is an example: 
The array is [1 3 -1 -3 5 3 6 7], and k is 3.

Window position Minimum value Maximum value
[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

Your task is to determine the maximum and minimum values in the sliding window at each position.

Input

The input consists of two lines. The first line contains two integers n and k which are the lengths of the array and the sliding window. There are n integers in the second line. 

Output

There are two lines in the output. The first line gives the minimum values in the window at each position, from left to right, respectively. The second line gives the maximum values. 

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

题目描述

现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。

例如:

The array is [1 3 -1 -3 5 3 6 7], and k = 3.

输入输出格式

输入格式:

输入一共有两行,第一行为n,k。

第二行为n个数(<INT_MAX).

输出格式:

输出共两行,第一行为每次窗口滑动的最小值

第二行为每次窗口滑动的最大值

输入输出样例

输入样例#1:

8 3
1 3 -1 -3 5 3 6 7
输出样例#1:

-1 -3 -3 -3 3 3
3 3 5 5 6 7

说明

50%的数据,n<=10^5

100%的数据,n<=10^6

思路:单调队列。

分别维护一个单调上升队列和一个单调下降队列即可。

拿区间最大值来说吧,一个上升队列,它的队首值就是区间最大值。

如果窗口向后滑动,首先,在满足队列单调的前提下,把新值加入(不一定真的加入)。

如果队首值等于要去掉的值,队首后移。

代码实现:

 #include<cstdio>
#define maxn 1000010
int n,k,s[maxn];
int a;
int h1,t1,q1[maxn],a1[maxn],l1;
int h2,t2,q2[maxn],a2[maxn],l2;
int main(){
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++){
scanf("%d",&s[i]);
a=h1-;h1=t1;
for(int j=a;j>=t1;j--) if(s[i]>=q1[j]){h1=j+;break;}
q1[h1++]=s[i];
if(i>k&&s[i-k]==q1[t1]) t1++;//因为判断先后的问题,一直RE一个点。
if(i>=k) a1[l1++]=q1[t1];
a=h2-;h2=t2;
for(int j=a;j>=t2;j--) if(s[i]<=q2[j]){h2=j+;break;}
q2[h2++]=s[i];
if(i>k&&s[i-k]==q2[t2]) t2++;
if(i>=k) a2[l2++]=q2[t2];
}
for(int i=;i<l1;i++) printf("%d ",a1[i]);putchar('\n');
for(int i=;i<l2;i++) printf("%d ",a2[i]);putchar('\n');
return ;
}

另一种写法(更工整些):

 #include<cstdio>
#define maxn 1000010
int n,k,s[maxn];
int a;
int h1,t1,q1[maxn],a1[maxn],l1;
int h2,t2,q2[maxn],a2[maxn],l2;
int main(){
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++){
scanf("%d",&s[i]);
q1[h1++]=;q2[h2++]=-;
for(int j=t1;j<h1;j++)
if(s[i]<q1[j]){q1[j]=s[i];h1=j+;break;}
if(i>k&&s[i-k]==q1[t1]) t1++;
if(i>=k) a1[l1++]=q1[t1];
for(int j=t2;j<h2;j++)
if(s[i]>q2[j]){q2[j]=s[i];h2=j+;break;}
if(i>k&&s[i-k]==q2[t2]) t2++;
if(i>=k) a2[l2++]=q2[t2];
}
for(int i=;i<l1;i++) printf("%d ",a1[i]);putchar('\n');
for(int i=;i<l2;i++) printf("%d ",a2[i]);putchar('\n');
return ;
}

也可以分开写:

 #include<cstdio>
#define maxn 1000010
int n,k,a,h,t;
int s[maxn],q[maxn];
int main(){
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++){
scanf("%d",&s[i]);
q[h++]=;
for(int j=t;j<h;j++) if(s[i]<q[j]){q[j]=s[i];h=j+;break;}
if(i>k&&s[i-k]==q[t]) t++;
if(i>=k) printf("%d ",q[t]);
}
putchar('\n');h=t=;
for(int i=;i<=n;i++){
q[h++]=-;
for(int j=t;j<h;j++) if(s[i]>q[j]){q[j]=s[i];h=j+;break;}
if(i>k&&s[i-k]==q[t]) t++;
if(i>=k) printf("%d ",q[t]);
}
putchar('\n');
return ;
}

越来越短。

最后被poj G++接受的代码(2266mm):

 #include<cstdio>
#define maxn 1000010
int n,k,s[maxn];
int a;
int h1,t1,q1[maxn],a1[maxn],l1;
int h2,t2,q2[maxn],a2[maxn],l2;
inline int abs(int x){return x<?-x:x;}
void write(int x){
if(x) write(x/);
else return;
putchar(x%+'');
}
int main(){
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++){
scanf("%d",&s[i]);
a=h1-;h1=t1;
for(int j=a;j>=t1;j--) if(s[i]>=q1[j]){h1=j+;break;}
q1[h1++]=s[i];
if(i>k&&s[i-k]==q1[t1]) t1++;
if(i>=k) a1[l1++]=q1[t1];
a=h2-;h2=t2;
for(int j=a;j>=t2;j--) if(s[i]<=q2[j]){h2=j+;break;}
q2[h2++]=s[i];
if(i>k&&s[i-k]==q2[t2]) t2++;
if(i>=k) a2[l2++]=q2[t2];
}
for(int i=;i<l1;i++){
if(a1[i]<) putchar('-');
write(abs(a1[i]));
if(!a1[i]) putchar('');
if(i<l1-) putchar(' ');
}
putchar('\n');
for(int i=;i<l2;i++){
if(a2[i]<) putchar('-');
write(abs(a2[i]));
if(!a2[i]) putchar('');
if(i<l2-) putchar(' ');
}
putchar('\n');
return ;
}

除了最后一个 G++ 格式都T了,C++却能A,不知道为什么。

洛谷70分T掉的线段树

 #include<cstdio>
const int maxn=4e6;
int n,k;
int s[maxn];
int t_min[maxn],t_max[maxn];
inline int min_(int x,int y){return x<y?x:y;}
inline int max_(int x,int y){return x>y?x:y;}
void build_min(int k,int l,int r){
if(l==r){
t_min[k]=s[l];
return;
}
int mid=l+r>>,ls=k<<,rs=ls|;
build_min(ls,l,mid);
build_min(rs,mid+,r);
t_min[k]=t_min[ls]<t_min[rs]?t_min[ls]:t_min[rs];
}
int search_min(int k,int l,int r,int al,int ar){
if(al==l&&ar==r) return t_min[k];
int ret=1e9,mid=l+r>>,ls=k<<,rs=ls|;
if(al<=mid) ret=min_(ret,search_min(ls,l,mid,al,min_(ar,mid)));
if(ar>mid) ret=min_(ret,search_min(rs,mid+,r,max_(al,mid+),ar));
return ret;
}
void build_max(int k,int l,int r){
if(l==r){
t_max[k]=s[l];
return;
}
int mid=l+r>>,ls=k<<,rs=ls|;
build_max(ls,l,mid);
build_max(rs,mid+,r);
t_max[k]=t_max[ls]>t_max[rs]?t_max[ls]:t_max[rs];
}
int search_max(int k,int l,int r,int al,int ar){
if(al==l&&ar==r) return t_max[k];
int ret=-1e9,mid=l+r>>,ls=k<<,rs=ls|;
if(al<=mid) ret=max_(ret,search_max(ls,l,mid,al,min_(ar,mid)));
if(ar>mid) ret=max_(ret,search_max(rs,mid+,r,max_(al,mid+),ar));
return ret;
}
int main(){
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++) scanf("%d",&s[i]);
build_min(,,n);
build_max(,,n);
for(int i=;i<=n-k+;i++)
printf("%d ",search_min(,,n,i,i+k-));
putchar('\n');
for(int i=;i<=n-k+;i++)
printf("%d ",search_max(,,n,i,i+k-));
putchar('\n');
return ;
}

常数优化十分可观的zkw线段树(洛谷 2275ms)

 #include<cstdio>
const int maxn=<<;
int n,k,m;
int t[maxn];
inline int min_(int x,int y){return x<y?x:y;}
inline int max_(int x,int y){return x>y?x:y;}
void build_min(){for(int i=m-;i>;i--) t[i]=min_(t[i<<],t[i<<|]);}
int search_min(int l,int r,int ret){
for(l+=m,r+=m;r-l!=;l>>=,r>>=){
if(~l&) ret=min_(ret,t[l^]);
if(r&) ret=min_(ret,t[r^]);
}
return ret;
}
void build_max(){for(int i=m-;i>;i--) t[i]=max_(t[i<<],t[i<<|]);}
int search_max(int l,int r,int ret){
for(l+=m,r+=m;r-l!=;l>>=,r>>=){
if(~l&) ret=max_(ret,t[l^]);
if(r&) ret=max_(ret,t[r^]);
}
return ret;
}
int main(){
scanf("%d%d",&n,&k);
for(m=;m<=n+;m<<=);
for(int i=;i<=n;i++) scanf("%d",t+m+i);
build_min();
for(int i=;i<=n-k;i++)
printf("%d ",search_min(i,i+k+,1e9));
putchar('\n');
build_max();
for(int i=;i<=n-k;i++)
printf("%d ",search_max(i,i+k+,-1e9));
putchar('\n');
return ;
}

题目来源:POJ,洛谷

Sliding Window(滑动窗口)的更多相关文章

  1. [POJ2823]Sliding Window 滑动窗口(单调队列)

    题意 刚学单调队列的时候做过 现在重新做一次 一个很经典的题目 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗 ...

  2. 【POJ 2823】【Luogu P1886】Sliding Window 滑动窗口

    POJ 2823 Luogu P1886 [解题思路] 这是一个单调队列算法的经典题目,几乎学习单调队列的人都接触过这题. 利用单调队列算法求出每一个固定区间内的最(大/小)值. 以下以最大值为例: ...

  3. Spark-Streaming之window滑动窗口应用

    Spark-Streaming之window滑动窗口应用,Spark Streaming提供了滑动窗口操作的支持,从而让我们可以对一个滑动窗口内的数据执行计算操作.每次掉落在窗口内的RDD的数据,会被 ...

  4. 57、Spark Streaming: window滑动窗口以及热点搜索词滑动统计案例

    一.window滑动窗口 1.概述 Spark Streaming提供了滑动窗口操作的支持,从而让我们可以对一个滑动窗口内的数据执行计算操作.每次掉落在窗口内的RDD的数据, 会被聚合起来执行计算操作 ...

  5. [LeetCode] Sliding Window Maximum 滑动窗口最大值

    Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...

  6. [LeetCode] Sliding Window Median 滑动窗口中位数

    Median is the middle value in an ordered integer list. If the size of the list is even, there is no ...

  7. LeetCode编程训练 - 滑动窗口(Sliding Window)

    滑动窗口基础 滑动窗口常用来解决求字符串子串问题,借助map和计数器,其能在O(n)时间复杂度求子串问题.滑动窗口和双指针(Two pointers)有些类似,可以理解为往同一个方向走的双指针.常用滑 ...

  8. [Swift]LeetCode239. 滑动窗口最大值 | Sliding Window Maximum

    Given an array nums, there is a sliding window of size k which is moving from the very left of the a ...

  9. 洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)

    To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每 ...

  10. POJ - 2823 Sliding Window (滑动窗口入门)

    An array of size n ≤ 10 6 is given to you. There is a sliding window of size kwhich is moving from t ...

随机推荐

  1. 水题 CodeForces 137A Postcards and photos

    题目传送门 /* 水! */ #include <cstdio> #include <cstring> #include <algorithm> using nam ...

  2. 理解 Java 构造函数不可以继承

    参考来源:http://www.52bowen.com/a/2604620.html

  3. 转 DOS(CMD)下批处理换行问题/命令行参数换行 arg ms-dos

    DOS(CMD)下批处理换行问题本人经常写一些DOS批处理文件,由于批处理中命令的参考较多且长,写在一行太不容易分辨,所以总想找个办法把一条命令分行来写,今天终于试成功两种方法.一.在CMD下,可以用 ...

  4. 2016天池-O2O优惠券使用预测竞赛总结

    第一次参加数据预测竞赛,发现还是挺有意思的.本文中的部分内容参考第一名“诗人都藏在水底”的解决方案. 从数据划分.特征提取.模型设计.模型融合/优化,整个业务流程得到了训练.作为新手在数据划分和模型训 ...

  5. [转]ASP.NET MVC HtmlHelper扩展之Calendar日期时间选择

    本文转自:http://blog.bossma.cn/asp_net_mvc/asp-net-mvc-htmlhelper-calendar-datetime-select/ 这里我们扩展HtmlHe ...

  6. 由ibatis向mybatis的转变

    我将项目引用的ibatis换成mybatis 过程中遇到一个问题:org.apache.ibatis.datasource.DataSourceException: Unknown DataSourc ...

  7. 第5章分布式系统模式 Singleton

    上下文 在某些情况下,特定类型的数据需要提供给应用程序中的其他所有对象使用.在大多数情况下,这种类型的数据在系统中还是唯一的.例如,用户界面只能有一个所有应用程序必须访问的鼠标指针.同样,企业解决方案 ...

  8. 北工大2017校赛 1101:要打车的FanZzz

    题目链接: http://bjutacm.openjudge.cn/lianxi/1101/ 思路: 二分 + 二分图最大匹配. 开始的时候我想直接用最小费用流模型,后来发现这样是错误的.因为这道题实 ...

  9. moment.js 两个时间段的截取

    var a = moment([2008, 9, 29]);var b = moment([2007, 0, 10]);console.log(a.diff(b,'months'));//‘month ...

  10. Python+selenium测试环境成功搭建,简单控制浏览器(firefox)接下来,继续学习其他浏览器上的测试环境搭建;学习Python语言,利用Python语言来写测试用例。加油!!!

    Python+selenium测试环境成功搭建,简单控制浏览器(firefox)接下来,继续学习其他浏览器上的测试环境搭建:学习Python语言,利用Python语言来写测试用例.加油!!!