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. 指向“”的 script 加载失败

    今天遇到了一个非常奇怪的问题:在某个同时的电脑上,所有浏览器无法打开某个页面,F12查看控制台,发现有一个黄色的 指向“xxxx.js”的 <script> 加载失败 的提示.该外部js文 ...

  2. [Usaco2013 Nov]No Change

    Description Farmer John is at the market to purchase supplies for his farm. He has in his pocket K c ...

  3. Android 性能优化(9)网络优化( 5)Optimizing Server-Initiated Network Use

    Optimizing Server-Initiated Network Use This lesson teaches you to Send Server Updates with GCM Netw ...

  4. 用SpringMVC实现的上传下载方式二(多文件上传)

    参考来源:      http://blog.csdn.net/qq_32953079/article/details/52290208 1.导入相关jar包 commons-fileupload.j ...

  5. 转发:吐血总结,彻底明白 python3 编码原理

    吐血总结,彻底明白 python3 编码原理 写的不错,转发学习一下,侵删.. 原文地址https://zhuanlan.zhihu.com/p/40834093 防止原文看不到了 这里粘贴复制一下: ...

  6. 394 Decode String 字符串解码

    给定一个经过编码的字符串,返回它解码后的字符串.编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次.注意 k 保证为正整数.你可以认 ...

  7. poj1240 Pre-Post-erous!

    思路: 根据前序序列和后序序列递归构造m叉树,确定每个节点的子节点数量.再用组合数公式累乘. 实现: #include <iostream> using namespace std; ][ ...

  8. 61配置nanopim1plus的HDMI为1080p输出

    61配置nanopim1plus的HDMI为1080p输出 大文实验室/大文哥 壹捌陆捌零陆捌捌陆捌贰 21504965 AT qq.com 完成时间:2018/4/4 10:21 版本:V1.1 开 ...

  9. Django基础之数据库增删改查

    Django中生成多个APP,每个APP下都有自己models模块,避免了多个APP之间数据的相互影响. 1.首先在APP的models下创建一个类 class UserInfo(models.Mod ...

  10. 【转】jvm收集器

    HotSpot JVM收集器 上面有7中收集器,分为两块,上面为新生代收集器,下面是老年代收集器.如果两个收集器之间存在连线,就说明它们可以搭配使用. Serial(串行GC)收集器 Serial收集 ...