洛谷-P2251 质量检测
题目大意
区间最值问题(RMQ)
思路
RMQ问题有很多种方法。本题数据只有1e6,比较小,所以我使用o(n)的方法。这题又是单调栈,但不完全是单调栈。
从前往后用i遍历[1,n],每个元素依次入栈,但是栈内要储存的不是产品质量A,而是该产品的下标。我们要维护一个栈底到栈顶单调产品质量递增,栈顶和栈顶元素(产品下标)之差不超过k的单调栈,从i>=k开始,每次i都要出栈底。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1e6+1000;
ll n , k ,l , r ;
ll a[N] , st[N] ;
int main(){
ios::sync_with_stdio(false);
cin>>n>>k ;
for(ll i = 1 ; i <= n ; i ++){
cin>>a[i];
}
l = r = 1 ;
for(ll i = 1 ; i <= n ; i ++){
while(l < r && a[st[r - 1]] >= a[i])r -- ;
st[r ++] = i ;//单调递增
if(st[r - 1] - st[l] == k){
l ++ ;//区间不超过k
}
//以上一个while一个if维护了上文描述的单调栈
if(i >= k)cout<<a[st[l]]<<"\n";
}
}
反思
做这个的时候,被区间的初始化、区间的衔接卡住了,其实特别简单。上面的代码我用了左闭右开的区间去做st,而左闭右闭也是可以的。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1e6+1000;
ll n , k ,l , r ;
ll a[N] , st[N] ;
int main(){
ios::sync_with_stdio(false);
cin>>n>>k ;
for(ll i = 1 ; i <= n ; i ++){
cin>>a[i];
}
l = 1;r = 0 ;
for(ll i = 1 ; i <= n ; i ++){
while(l <= r && a[st[r]] >= a[i])r -- ;
st[++r] = i ;
if(st[r] - st[l] == k){
l ++ ;
}
if(i >= k)cout<<a[st[l]]<<"\n";
}
}

浙公网安备 33010602011771号