单调队列

洛谷P2032

一句话题意:给一个长为 \(n\) 的序列,有一长为k的滑动窗口,从左往右滑,问每次窗口内的最大值。 \((1 \le n \le 2 \times 10^6\))

单调队列:一种队列,用于求递增区间 \(min, max\) 。具体来说,对定长区间求 \(max\) ,每加入一个点,先将队列中不符合区间长度要求的弹出,再判断,弹出所有权值比当前元素更小的点,再插入当前元素。这样做会使队列中保持单调递减,于是队头一定是最大值。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
int n, len, a[N];
int q[N], hd = 1, tl;
int main()
{
	scanf("%d%d", &n, &len);
	for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
	for(int i = 1; i <= n; ++i){
		while(hd <= tl && q[hd] < i - len + 1) ++hd;//催命官 
		while(hd <= tl && a[q[tl]] < a[i]) --tl;//街头霸王 
		q[++tl] = i;
		if(i >= len) cout << a[q[hd]] <<'\n';
	}
	return 0;
}#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
bool mp[N][N];
int l[N][N], r[N][N], h[N][N];
int stk[N], top;
int n, m;
long long res;
char v;
inline int read()
{
	int x = 0;
	while(!isdigit(v)) v = getchar();
	while(isdigit(v)) x = (x << 1) + (x << 3) + v - 48, v = getchar();
	return x;
}
int main()
{
	n = read(); m = read();
	for(int i = 1; i <= n; ++i)
	    for(int j = 1 ; j <= m; ++j)
	    {
	    	while((v ^ '*') && (v ^ '.')) v = getchar();
	    	mp[i][j] = (v ^ '*') ? true : false;
	    	v = getchar();
	    }
	
	for(int i = 1; i <= n; ++i)
	    for(int j = 1; j <= m; ++j)
	        if(mp[i][j])
	        	h[i][j] = h[i - 1][j] + 1;
	
	for(int i = 1; i <= n; ++i)
	{
		top = 0;
	    for(int j = m; j; --j)
	   	 	{
	   	    	while(top && h[i][j] <= h[i][stk[top]]) 
	   	    	{
	   	    		l[i][stk[top]] = j;
	   	    		--top;
				}
			    stk[++top] = j;
	    	}
	    while(top)
	    {
	    	l[i][stk[top]] = 0;
	    	--top;
		}
    }
    
    for(int i = 1; i <= n; ++i)
	{
		top = 0;
	    for(int j = 1; j <= m; ++j)
	   	 	{
	   	    	while(top && h[i][j] < h[i][stk[top]]) 
	   	    	{
	   	    		r[i][stk[top]] = j;
	   	    		--top;
				}
			    stk[++top] = j;
	    	}
	    while(top)
	    {
	    	r[i][stk[top]] = m + 1;
	    	--top;
		}
    }
    
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= m; ++j)
            res += h[i][j] * (j - l[i][j]) * (r[i][j] - j);
            
	cout << res;
	return 0;
}
posted @ 2022-04-09 14:30  Faker_yu  阅读(34)  评论(0)    收藏  举报