Sliding Window (单调队列)
来源:互联网 发布:钱龙软件怎么样 编辑:程序博客网 时间:2024/06/10 13:34
Sliding Window
Time Limit : 24000/12000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 165 Accepted Submission(s) : 20
The array is [1 3 -1 -3 5 3 6 7], and k is 3.
Your task is to determine the maximum and minimum values in the sliding window at each position.
8 31 3 -1 -3 5 3 6 7
-1 -3 -3 -3 3 33 3 5 5 6 7
题意:很简单。
思路:转自:http://www.mamicode.com/info-detail-951261.html
这个问题相当于一个数据流(数列a)在不断地到来,而数据是不断过期的,相当于我们只能保存有限的数据(sliding window中的数据,此题中就是窗口的宽度w),对于到来的查询(此题中查询是每时刻都有的),我们要返回当前滑动窗口中的最大值\最小值。注意,元素是不断过期的。
解决这个问题可以使用一种叫做单调队列的数据结构,它维护这样一种队列:
a)从队头到队尾,元素在我们所关注的指标下是递减的(严格递减,而不是非递增),比如查询如果每次问的是窗口内的最小值,那么队列中元素从左至右就应该递增,如果每次问的是窗口内的最大值,则应该递减,依此类推。这是为了保证每次查询只需要取队头元素。
b)从队头到队尾,元素对应的时刻(此题中是该元素在数列a中的下标)是递增的,但不要求连续,这是为了保证最左面的元素总是最先过期,且每当有新元素来临的时候一定是插入队尾。
满足以上两点的队列就是单调队列,首先,只有第一个元素的序列一定是单调队列。
那么怎么维护这个单调队列呢?无非是处理插入和查询两个操作。
对于插入,由于性质b,因此来的新元素插入到队列的最后就能维持b)继续成立。但是为了维护a)的成立,即元素在我们关注的指标下递减,从队尾插入新元素的时候可能要删除队尾的一些元素,具体说来就是,找到第一个大于(在所关注指标下)新元素的元素,删除其后所有元素,并将新元素插于其后。因为所有被删除的元素都比新元素要小,而且比新元素要旧,因此在以后的任何查询中都不可能成为答案,所以可以放心删除。
对于查询,由于性质b,因此所有该时刻过期的元素一定都集中在队头,因此利用查询的时机删除队头所有过期的元素,在不含过期元素后,队头得元素就是查询的答案(性质a),将其返回即可。
由于每个元素都进队出队一次,因此摊销复杂度为O(n)。
代码:
#include<iostream>#include<string>#include<cstdio>#include<algorithm>#include<cmath>#include<iomanip>#include<queue>#include<cstring>#include<map>using namespace std;int N,M,a[1000005],b1[1000005],v[1000005],S,mid,MM[1000005];//a存储数据,b1是队列,v记录符号,mm记录最大或最小值。void maxx(){ int i,j,k,l; l=0;k=-1;j=0; for(i=1;i<=M;i++) //第一组里 { while(k>=0&&a[i]>=b1[k]) k--; b1[++k]=a[i]; v[k]=i; } MM[l++]=b1[0]; for(i=M+1;i<=N;i++) {if(v[j]<i-M+1) j++; //如果对头出范围了,则对头前移。 while(k>=j&&a[i]>=b1[k]) k--; b1[++k]=a[i]; v[k]=i; MM[l++]=b1[j]; } for(i=0;i<l-1;i++) cout<<MM[i]<<" "; cout<<MM[l-1]<<endl;}void minn(){ memset(v,0,sizeof(v)); memset(b1,0,sizeof(b1)); memset(MM,0,sizeof(MM)); int i,j,k,l; l=0;k=-1;j=0; for(i=1;i<=M;i++) { while(k>=0&&a[i]<=b1[k]) k--; b1[++k]=a[i]; v[k]=i; } MM[l++]=b1[0]; for(i=M+1;i<=N;i++) { if(v[j]<i-M+1) j++; while(k>=j&&a[i]<=b1[k]) k--; b1[++k]=a[i]; v[k]=i; MM[l++]=b1[j]; } for(i=0;i<l-1;i++) cout<<MM[i]<<" "; cout<<MM[l-1]<<endl;}int main(){ int i; while(cin>>N>>M) { for(i=1;i<=N;i++) scanf("%d",&a[i]); minn(); maxx(); } return 0;}
我得代码:第一次提交竟然AC了,但是以后提交全是TLE,卡时间看进去了 哈哈。。。附上代码:
#include <iostream>#include <cstring>#include <string>#include <stdio.h>#include <algorithm>#define inf 0x3f3f3f3fusing namespace std;int minn[1000000],maxn[1000000];int a[1000000];int n,k;int num;void cal(int pre,int cur){ int i; int maxl=-inf,minl=inf; for(i=pre;i<=cur;i++) { if(maxl<a[i])maxl=a[i]; if(minl>a[i])minl=a[i]; } maxn[num]=maxl; minn[num++]=minl;}int main(){ cin>>n>>k; int i; num=0; for(i=1;i<=n;i++) { cin>>a[i]; } int cur=k; int pre=1; while(1) { if(cur>n) {break;} cal(pre,cur); pre+=1; cur+=1; } for(i=0;i<num;i++) cout<<minn[i]<<' '; cout<<endl; for(i=0;i<num;i++) cout<<maxn[i]<<' '; cout<<endl; return 0;}
- Sliding Window (单调队列)
- Sliding Window (单调队列)
- Sliding Window(单调队列)
- poj 2823 Sliding Window(单调队列)
- POJ 2823 Sliding Window(单调队列)
- POJ 2823 Sliding Window(单调队列)
- poj 2823 Sliding Window(单调队列)
- poj 2823 Sliding Window ( 单调队列 )
- POJ 2823 Sliding Window (单调队列)
- poj 2823 Sliding Window(单调队列)
- poj - 2823 - Sliding Window(单调队列)
- POJ 2823 Sliding Window (单调队列)
- POJ 2823 Sliding Window(单调队列)
- POJ 2823 Sliding Window(单调队列)
- POJ2823--Sliding Window(单调队列)
- POJ 2823 Sliding Window(单调队列)
- POJ 2823 Sliding Window (单调队列)
- POJ 2823 Sliding Window(单调队列)
- javascript测试框架mocha
- 虚拟机kali连wifi的问题
- node中使用consolidate后报错Cannot find module 'ejs'
- mysql搭建备库---使用xtrabackup
- python数据结构之列表
- Sliding Window (单调队列)
- 安装wamp遇到的问题总结
- 正则表达式
- 8.11 模拟
- 【2017/8/11】Linux7 简单安装nginx
- HDU 5212 Code(容斥 或 莫比乌斯反演)
- git最常用!最实用!最基本的命令解析!绝对够用!
- 希尔排序(shell sort)
- tf.py_func errors in freeze_graph