洛谷-P2251 质量检测

洛谷-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";
		
	}
	
}
posted @ 2021-09-06 10:12  tyrii  阅读(126)  评论(0)    收藏  举报