1. 程式人生 > >【POJ 2823】Sliding Window 【滑動視窗/單調佇列入門

【POJ 2823】Sliding Window 【滑動視窗/單調佇列入門

題目大意

輸入一個長度為n(n≤≤106106)的數列,給定一個長度為k的視窗,讓這個視窗在數列上移動,求移動到每個位置視窗中包含數的最大值和最小值。即設序列為A1,A2,,AnA1,A2,…,An,設f(i)=minAik+1Aik+1,Aik+2Aik+2,,AkAkf(i)=min {Ai−k+1Ai−k+1,Ai−k+2Ai−k+2,…,AkAk},g(i)=maxAik+1Aik+1,Aik+2Aik+2,,AkAkg(i)=max{Ai−k+1Ai−k+1,Ai−k+2Ai−k+2,…,AkAk}

求:f(k),f(k+1),…,f(n) g(k),g(k+1),…,g(n).

紫書P241 下面給出程式碼實現:

版本一:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define g() getchar()
#define f(i,s,t) for(int i=s;i<=t;i++)
char ch;bool flag;template<class T>inline void r(T &x){ for(flag=0,ch=g();!isdigit(ch);ch=='-'?flag=1:0,ch=g()); for(x=0;isdigit(ch);x=(x<<3)+(x<<1)+ch-'0',ch=g()); flag?x=-x:0; } const int maxn = 1000010; int a[maxn],n,k,que[maxn],ans[maxn]; int main(){ r(n),r(k);f(i,1,n)r(a[i]); int
head=1,tail=1;que[1]=1;ans[1]=a[1]; f(i,2,n){ while(head<=tail&&a[i]<=a[que[tail]])tail--; que[++tail]=i; if(head<=tail&&que[head]<(i-k+1))head++; ans[i] = a[que[head]];//記錄當前最值 } f(i,k,n)printf("%d ",ans[i]);putchar('\n'); head = 1,tail = 1,que[1] = 1;ans[1]=a[1]; f(i,2,n){ while(head<=tail&&a[i]>=a[que[tail]])tail--; que[++tail]=i; if(head<=tail&&que[head]<(i-k+1))head++; ans[i] = a[que[head]];//記錄當前最值 } f(i,k,n)printf("%d ",ans[i]); return 0; }

(G++要TLE,c++AC,不知道什麼情況…)
版本二:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue> 
using namespace std;
#define g() getchar()
#define f(i,s,t) for(int i=s;i<=t;i++)
char ch;bool flag;template<class T>inline void r(T &x){
 for(flag=0,ch=g();!isdigit(ch);ch=='-'?flag=1:0,ch=g());
 for(x=0;isdigit(ch);x=(x<<3)+(x<<1)+ch-'0',ch=g());
 flag?x=-x:0; 
}
const int maxn = 1000010;
int a[maxn],n,k,ans[maxn];
deque<int> que;
int main(){
 r(n),r(k);f(i,1,n)r(a[i]);
 que.push_front(1);ans[1]=a[1];
 f(i,2,n){
  while(!que.empty()&&a[i]<=a[que.back()])que.pop_back();
  que.push_back(i);
  if(!que.empty()&&que.front()<(i-k+1))que.pop_front();
  ans[i] = a[que.front()];//記錄當前最值 
 }
 f(i,k,n)printf("%d ",ans[i]);putchar('\n');
 while(!que.empty())que.pop_back();
 que.push_front(1),ans[1]=a[1];
 f(i,2,n){
  while(!que.empty()&&a[i]>=a[que.back()])que.pop_back();
  que.push_back(i);
  if(!que.empty()&&que.front()<(i-k+1))que.pop_front();
  ans[i] = a[que.front()];//記錄當前最值 
 }
 f(i,k,n)printf("%d ",ans[i]);
 return 0;
}