其实单调队列不一定只能维护定长区间,只要这个区间的l、r一直单调递增就行了...
单调队列真的特别不容易打对,特别是变种,经常要花1个多小时调试
还得加深理解啊...


#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<ctime> #include<cstdlib> #include<queue> using namespace std; int maxsize;//维持的长度 int que[1000005];//单调队列 int data[1000005];//维护的数据 int head,tail; int n,m; int main() { //这里以维护 长度为m的区间中的最大值 为例 cin>>n>>m; head=0; tail=0; for(int i=1; i<=n; i++) { scanf("%d",&data[i]); } for(int i=1; i<=n; i++) { for(; head<tail;) { if(data[que[tail-1]]>data[i]) { break; } tail--; } que[tail]=i; tail++; if(que[head]+m<=i) { head++; } printf("%d ",data[que[head]]); } return 0; }


#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; struct MonoQue{ int data[1000000];//维护的数据 int que[1000000];//单调队列 int head,tail; void init(){ head=0;tail=0; } void push(int id){ for(;head<tail;){ if(data[que[tail-1]]>=data[id]) tail--; else break; } que[tail]=id; tail++; } void pop(){ head++; } int top(){ return que[head]; } }uuz; int n,lim; int main(){//这里以维护 长度为m的区间中的最小值 为例 cin>>n>>lim; for(int i=1;i<=n;i++){ scanf("%d",&uuz.data[i]); } for(int i=1;i<=n;i++){ uuz.push(i); for(;;){ if(uuz.top()<i-lim+1) uuz.pop(); else break; } printf("%d ",uuz.data[uuz.top()]); } return 0; }
模板题:
变种: