数据结构——单调队列

定义

内部元素单调递增/递减的队列操作

作用

求出一个数组内第一个大于等于一个数x的数
求出数组里每个定长连续区间的最值

原理

加入一个元素时,若队列不为空且队尾元素大于/小于当前元素的值时,弹出队尾,重复该操作直至队列为空或队尾元素小于等于/大于等于新元素,新元素入队,保证队列里的元素始终单调递增/减。

模板

while(!dq.empty()) dq.pop_back();
for(int j = 1; j <= b; j++){
	nw = num[j];
	while(!dq.empty() && dq.back() > nw) dq.pop_back();
	dq.push_back(nw);	
}

例题

codeforces-1195E OpenStreetMap

Description

Seryozha conducts a course dedicated to building a map of heights of Stepanovo recreation center. He laid a rectangle grid of size n×m cells on a map (rows of grid are numbered from 1 to n from north to south, and columns are numbered from 1 to m from west to east). After that he measured the average height of each cell above Rybinsk sea level and obtained a matrix of heights of size n×m. The cell (i,j) lies on the intersection of the i-th row and the j-th column and has height hi,j.

Seryozha is going to look at the result of his work in the browser. The screen of Seryozha’s laptop can fit a subrectangle of size a×b of matrix of heights (1≤a≤n, 1≤b≤m). Seryozha tries to decide how the weather can affect the recreation center — for example, if it rains, where all the rainwater will gather. To do so, he is going to find the cell having minimum height among all cells that are shown on the screen of his laptop.

Help Seryozha to calculate the sum of heights of such cells for all possible subrectangles he can see on his screen. In other words, you have to calculate the sum of minimum heights in submatrices of size a×b with top left corners in (i,j) over all 1≤i≤n−a+1 and 1≤j≤m−b+1.

Consider the sequence gi=(gi−1⋅x+y)modz. You are given integers g0, x, y and z. By miraculous coincidence, hi,j=g(i−1)⋅m+j−1 ((i−1)⋅m+j−1 is the index).

Input

The first line of the input contains four integers n, m, a and b (1≤n,m≤3000, 1≤a≤n, 1≤b≤m) — the number of rows and columns in the matrix Seryozha has, and the number of rows and columns that can be shown on the screen of the laptop, respectively.

The second line of the input contains four integers g0, x, y and z (0≤g0,x,y<z≤109).

Output

Print a single integer — the answer to the problem.

Example

input

3 4 2 1
1 2 3 59

output

111

分析

求所有大小相同的区间内的最小值之和,典型的单调队列求区间定长段最值,只不过这里是二维的,所以要处理两次而已。
AC代码:

#include <cstdio>
#include <queue>
#include <iostream>
using namespace std;
 
#define ll long long
#define maxn 3000 + 5
ll h[maxn][maxn];
struct Node{
	int dex;
	ll val;
	bool operator <(const Node A) {return val<A.val;}
	bool operator >(const Node A) {return val>A.val;}
} down[maxn];
Node up[maxn];
deque <Node> dq;
 
int main()
{
	int n, m, a, b;
	ll g, x, y, z;
	scanf("%d%d%d%d", &n, &m, &a, &b);
	cin >> g >> x >> y >>z;
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= m; j++){
			h[i][j] = g;
			g = (x*g + y) % z;
		}
	}
	
	Node nw;
	for(int i = 1; i <= n; i++)	{
		while(!dq.empty()) dq.pop_back();
		for(int j = 1; j <= b; j++){
			nw.dex = j, nw.val = h[i][j];
			while(!dq.empty() && dq.back().val > nw.val) dq.pop_back();
			dq.push_back(nw);
			h[i][1] = dq.front().val;		
		}
 		for(int j = 2; j <= m-b+1; j++){
 			nw.dex = j + b - 1, nw.val = h[i][nw.dex];
 			while(!dq.empty() && dq.front().dex < j) dq.pop_front();
 			while(!dq.empty() && dq.back().val > nw.val) dq.pop_back();
 			dq.push_back(nw);
 			h[i][j] = dq.front().val;
		}
	}
	
	for(int i = 1; i <= m-b+1; i++)	{
		while(!dq.empty()) dq.pop_back();
		for(int j = 1; j <= a; j++){
			nw.dex = j, nw.val = h[j][i];
			while(!dq.empty() && dq.back().val > nw.val) dq.pop_back();
			dq.push_back(nw);
			h[1][i] = dq.front().val;		
		}
 		for(int j = 2; j <= n-a+1; j++){
 			nw.dex = j + a - 1, nw.val = h[nw.dex][i];
 			while(!dq.empty() && dq.front().dex < j) dq.pop_front();
 			while(!dq.empty() && dq.back().val > nw.val) dq.pop_back();
 			dq.push_back(nw);
 			h[j][i] = dq.front().val;
		}
	}
	ll res = 0;
	for(int i = 1; i <= n-a+1; i++)
		for(int j = 1; j <= m-b+1; j++)
			res += h[i][j];
	printf("%lld\n", res);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值