单调栈和单调队列通常的做法,用栈或者队列来存储元素,用栈和队列来考虑暴力的模拟方法,然后观察栈和队列里面的元素,看看是否有一些元素完全没用,把这些元素删掉,看看剩余元素是否有单调性,有单调性就可以看看题义,做出来了。
单调栈:
求一个数列中比第i个数小且最近的数
原数组a[i] 3 4 2 7 5
第i个比a[i]小且最近的的数(从第i个数开始往左数) -1 3 -1 2 2
- #include <iostream>
- using namespace std;
- const int N=10010;
- int n;
- int stk[N],tt;
- int main()
- {
- ios_base::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- cin>>n;
- for(int i=0;i<n;i++){
- int x;
- cin>>x;
- while(tt&&stk[tt]>=x)tt--;
- if(tt)cout<<stk[tt]<<" ";
- else cout<<-1<<" ";
- stk[++tt]=x;
- }
- return 0;
- }
单调队列:
acwing 滑动窗口
- #include <iostream>
- using namespace std;
- const int N=1000010;
- int n,k;
- int a[N],q[N];
- int main()
- {
- scanf("%d%d",&n,&k);
- for(int i=0;i<n;i++)scanf("%d",&a[i]);
- int hh=0,tt=-1;
- for(int i=0;i<n;i++){
- //hh<=tt队列不为空,负责队列为空
- //判断队头是否已经滑出窗口
- if(hh<=tt&&i-k+1>q[hh])hh++;
- //判断新加的数是否会让前面的数删除
- while(hh<=tt&&a[q[tt]]>=a[i]) tt--;
- q[++tt]=i;
- //当不够k个数的话不输出,够了k个数才输出
- if(i>=k-1)printf("%d ",a[q[hh]]);
- }
- puts(" ");
- hh=0,tt=-1;
- for(int i=0;i<n;i++){
- //hh<=tt队列不为空,负责队列为空
- //判断队头是否已经滑出窗口
- if(hh<=tt&&i-k+1>q[hh])hh++;
- //判断新加的数是否会让前面的数删除
- while(hh<=tt&&a[q[tt]]<=a[i]) tt--;
- q[++tt]=i;
- //当不够k个数的话不输出,够了k个数才输出
- if(i>=k-1)printf("%d ",a[q[hh]]);
- }
- puts(" ");
- return 0;
- }