题意:
给出序列,找出每个连续长度为k的子序列的最大值和最小值。
思路:
裸单调队列...
单调队列这东西用的真的非常局限,大概只能用到这种情景中==
简单说一下维护:
添加元素,为了保持单调性,排除队尾所有比要添加的元素大或者小的元素。
出队,出队之前要保证要出队的元素在当前范围内,如果不在先把不在的都出队。
这题可以只记录索引号,所以内存还是可以优化的,懒得写了。
坑:
复制自己的两段代码忘记改其中一个大于号。WA了一上午。不要不要的。
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; struct st { int num,pos; }; int tmp[1000010]; st ansma[1000010]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&tmp[i]); } if(m==0) { for(int i=0;i<=n;i++) { printf("%d",tmp[i]); if(i!=n) printf(" "); } printf(" "); for(int i=0;i<=n;i++) { printf("%d",tmp[i]); if(i!=n) printf(" "); } printf(" "); return 0; } int st,ed; st=1;ed=1; ansma[1].num=tmp[1]; ansma[1].pos=1; for(int i=2;i<m;i++) { while(tmp[i]<=ansma[ed].num&&ed>=st) { ed--; } ed++; ansma[ed].num=tmp[i]; ansma[ed].pos=i; } for(int i=m;i<=n;i++) { while(tmp[i]<=ansma[ed].num&&ed>=st) { ed--; } ed++; ansma[ed].num=tmp[i]; ansma[ed].pos=i; while(ansma[st].pos<=i-m&&st<ed) { st++; } printf("%d",ansma[st].num); if(i!=n) printf(" "); } printf(" "); st=1;ed=1; ansma[1].num=tmp[1]; ansma[1].pos=1; for(int i=2;i<m;i++) { while(tmp[i]>=ansma[ed].num&&ed>=st) { ed--; } ed++; ansma[ed].num=tmp[i]; ansma[ed].pos=i; } for(int i=m;i<=n;i++) { while(tmp[i]>=ansma[ed].num&&ed>=st) { ed--; } ed++; ansma[ed].num=tmp[i]; ansma[ed].pos=i; while(ansma[st].pos<=i-m&&st<ed) { st++; } printf("%d",ansma[st].num); if(i!=n) printf(" "); } printf(" "); }