Sliding Window(滑动窗口)
Time Limit: 12000MS | Memory Limit: 65536K | |
Total Submissions: 58002 | Accepted: 16616 | |
Case Time Limit: 5000MS |
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
Output
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).
输出格式:
输出共两行,第一行为每次窗口滑动的最小值
第二行为每次窗口滑动的最大值
输入输出样例
8 3
1 3 -1 -3 5 3 6 7
-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(滑动窗口)的更多相关文章
- [POJ2823]Sliding Window 滑动窗口(单调队列)
题意 刚学单调队列的时候做过 现在重新做一次 一个很经典的题目 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗 ...
- 【POJ 2823】【Luogu P1886】Sliding Window 滑动窗口
POJ 2823 Luogu P1886 [解题思路] 这是一个单调队列算法的经典题目,几乎学习单调队列的人都接触过这题. 利用单调队列算法求出每一个固定区间内的最(大/小)值. 以下以最大值为例: ...
- Spark-Streaming之window滑动窗口应用
Spark-Streaming之window滑动窗口应用,Spark Streaming提供了滑动窗口操作的支持,从而让我们可以对一个滑动窗口内的数据执行计算操作.每次掉落在窗口内的RDD的数据,会被 ...
- 57、Spark Streaming: window滑动窗口以及热点搜索词滑动统计案例
一.window滑动窗口 1.概述 Spark Streaming提供了滑动窗口操作的支持,从而让我们可以对一个滑动窗口内的数据执行计算操作.每次掉落在窗口内的RDD的数据, 会被聚合起来执行计算操作 ...
- [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 ...
- [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 ...
- LeetCode编程训练 - 滑动窗口(Sliding Window)
滑动窗口基础 滑动窗口常用来解决求字符串子串问题,借助map和计数器,其能在O(n)时间复杂度求子串问题.滑动窗口和双指针(Two pointers)有些类似,可以理解为往同一个方向走的双指针.常用滑 ...
- [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 ...
- 洛谷P1886 滑动窗口(POJ.2823 Sliding Window)(区间最值)
To 洛谷.1886 滑动窗口 To POJ.2823 Sliding Window 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每 ...
- 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 ...
随机推荐
- HTML和JSP的不同及优缺点
HTML(Hypertext Markup Language)文本标记语言,它是静态页面,和JavaScript一样解释性语言,为什么说是解释性语言呢?因为,只要你有一个浏览器那么它就可以正常显示出来 ...
- 第八届河南省省赛 A.挑战密室
挑战密室 时间限制: ms | 内存限制: KB 难度: 描述 R组织的特工Dr. Kong 为了寻找丢失的超体元素,不幸陷入WTO密室.Dr. Kong必须尽快找到解锁密码逃离,否则几分钟之后,WT ...
- [ TJOI 2012 ] 防御
\(\\\) Description 有 \(n\) 人,第 \(i\) 个人有一个护甲值 \(a_i\). 有 \(m\) 次操作,分为以下两种: \(A\ l\ r\ x\) 对编号在 \([l, ...
- JavaScript(十三)面向对象
面向对象 面向对象的过程 通过new 构造函数 生成的对象来执行, 类似于事件的执行 this指向函数,然后再把这个函数赋值给一个实例 所以在函数内的this 就指到了实例上 function ...
- QQ应用前景与范围文档
QQ软件 前景与范围文档 当前版本: 版本1 作 者: 李飞 完成日期: 2013年11月3日 1. 业务需求 1.1 应用背景 20世纪后期网络的应用和21世纪的飞速发展,网络已经 ...
- NX自动出图 发布啦
经过4个月的努力,终于面世啦!!!!1.安装文件 :http://yunpan.cn/Q49TWSJmy2i5Z 请下载后,按照“安装说明.txt ”进行安装!2.学习视频:http://yun ...
- canvas一周一练 -- canvas绘制立体文字(2)
运行效果: <!DOCTYPE html> <html> <head> </head> <body> <canvas id=" ...
- UIPageViewController 翻页、新手引导--UIScrollView:pagingEnabled
UIPageViewController 翻页.新手引导--UIScrollView:pagingEnabled
- 基于 CentOS 搭建Seafile个人网盘
一.安装 Seafile 安装依赖环境使用 yum 安装 Python 及 MySQL: yum install python python-setuptools python-imaging pyt ...
- 搭建linux环境:如何在vmware安装linux虚拟机??
本来不想再整一遍的,奈何分布式压测呀,呀呀呀呀呀呀 1.安装linux虚机 (1)在桌面上双击VMware Workstation图标后启动虚拟机,鼠标单击文件,选择新的虚拟机: (2)单击“next ...