单调队列就是维护一个队列,使得该队列从队首到队尾成单调递增或是单调递减。
做法就是每向队列里加入一个元素就判断该元素是不是比队尾元素大(以递减序列为例),是的话就将队尾元素出列,直到该元素比队尾元素小,然后将该元素放置队尾。
这么久了一直不明白单调队列的实现,现在看来,原来这么简单。。。。。
单调栈的原理相似,只不过一个是栈,一个是队列而已
两道例题:
代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int N=1000000*2; 6 int q[N],head,tail,bz[N]; 7 int a[N],n,pos[N],k; 8 int main() 9 { 10 scanf("%d%d",&n,&k); 11 for(int i=1;i<=n;++i) 12 scanf("%d",&a[i]); 13 if(k==1)//日常卡数据,请忽略 14 { 15 for(int i=1;i<=n;++i) 16 printf("%d ",a[i]); 17 printf("\n"); 18 for(int i=1;i<=n;++i) 19 printf("%d ",a[i]); 20 return 0; 21 } 22 q[++tail]=a[1];pos[tail]=1; 23 for(int i=2;i<k;++i) 24 { 25 while(a[i]<q[tail]&&tail>head) --tail; 26 q[++tail]=a[i]; 27 pos[tail]=i; 28 } 29 for(int i=k;i<=n;++i) 30 { 31 bz[i-k]=1; 32 while(bz[pos[head]]==1) head++; 33 while((a[i]<q[tail]||bz[pos[tail]])&&tail>=head) 34 --tail; 35 q[++tail]=a[i]; 36 pos[tail]=i; 37 printf("%d ",q[head]); 38 } 39 printf("\n"); 40 memset(q,0,sizeof(q)); 41 memset(bz,0,sizeof(bz)); 42 memset(pos,0,sizeof(pos)); 43 tail=1;head=1; 44 q[++tail]=a[1];pos[tail]=1; 45 for(int i=2;i<k;++i) 46 { 47 while(a[i]>q[tail]&&tail>=head) --tail; 48 q[++tail]=a[i]; 49 pos[tail]=i; 50 } 51 for(int i=k;i<=n;++i) 52 { 53 bz[i-k]=1; 54 while(bz[pos[head]]==1) head++; 55 while((a[i]>q[tail]||bz[pos[tail]])&&tail>=head) 56 --tail; 57 q[++tail]=a[i]; 58 pos[tail]=i; 59 printf("%d ",q[head]); 60 } 61 return 0; 62 }
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 int n,m; 5 const int N=500000*2; 6 int bz[N],pos[N],a[N],q[N],sum[N]; 7 int head=1,tail=0,ans=-0x7fffffff; 8 int main() 9 { 10 scanf("%d%d",&n,&m); 11 for(int i=1;i<=n;++i) 12 { 13 scanf("%d",&a[i]); 14 sum[i]=a[i]+sum[i-1]; 15 } 16 m++; 17 for(int i=1;i<=n;++i) 18 { 19 if(i>m) bz[i-m]=1; 20 while(bz[pos[head]]) head++; 21 while((sum[i]<q[tail]||bz[pos[tail]])&&tail>=head) tail--; 22 q[++tail]=sum[i]; 23 pos[tail]=i; 24 ans=max(ans,sum[i]-q[head]); 25 } 26 printf("%d",ans); 27 return 0; 28 }