您的位置:首页 > 其它

(poj 2823 Sliding Window)<单调队列裸题>

2017-08-17 20:25 519 查看
传送门

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: