(poj 2823 Sliding Window)<单调队列裸题>
2017-08-17 20:25
519 查看
传送门
假设我们将数放在数组a中,设其中有两个数满足:i<j && a[i]<a[j],那么在一个窗口范围内计算最大值时,a[i]就是无用的,即如果一个数比另一个数小,而且它的位置更靠前,那它一点前途也没有,既不可能成为当前窗口的最大值,窗口移动后的竞争力也很差,因此直接将它移出队列。
经过这样维护的队列,一定是单调递减的,队头即为最大值
计算最小值:将原数列每个数乘-1,做一遍最大值
Solution
单调队列就是一个答案的集合,维护一个单调队列就是将有可能成为答案的数加入队列,将不可能成为答案的数移出或不加入队列。这样的好处是可以O(1)的从队头取出答案,否则需要在“窗口”的范围内枚举答案,妥妥超时假设我们将数放在数组a中,设其中有两个数满足:i<j && a[i]<a[j],那么在一个窗口范围内计算最大值时,a[i]就是无用的,即如果一个数比另一个数小,而且它的位置更靠前,那它一点前途也没有,既不可能成为当前窗口的最大值,窗口移动后的竞争力也很差,因此直接将它移出队列。
经过这样维护的队列,一定是单调递减的,队头即为最大值
计算最小值:将原数列每个数乘-1,做一遍最大值
Code
// by spli #include<cstdio> #include<algorithm> #include<iostream> #include<cstring> using namespace std; const int N=2000010; int n,k; int a ,q ,L,R; void work(int *a,int t){ L=1;R=0;// for(int i=1;i<=n;++i){ while(L<=R&&a[i]>=a[q[R]]) R--; q[++R]=i; if(q[R]-k+1>q[L]) L++; if(i>=k) printf("%d ",a[q[L]]*t); } cout<<endl; return; } int main(){ scanf("%d%d",&n,&k); for(int i=1;i<=n;++i) scanf("%d",&a[i]); if(k==1){//特判k==1的情况,可能不需要 for(int i=1;i<=n;++i) printf("%d ",a[i]); cout<<endl; for(int i=1;i<=n;++i) printf("%d ",a[i]); return 0; } for(int i=1;i<=n;++i) a[i]=-a[i]; work(a,-1); for(int i=1;i<=n;++i) a[i]=-a[i]; work(a,1); return 0; }
相关文章推荐
- 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 (单调队列)
- POJ 2823 Sliding Window(单调队列||线段树)
- 单调队列优化多重背包(含构造问题<POJ 1742 coin>)
- 【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 - dp&单调队列优化