Codeforces 1195E OpenStreetMap monotone queue Queue sets monotone

Meaning of the questions: to give you a n * m matrix, asked smallest element of a * b all of the sub-matrices and how much. Title given data generator matrix number.

Thinking: If the problem is one-dimensional, i.e., find all of the minimum interval and the elements, monotone queue O (n) can do. For that matter, we give each line a monotonous build queue, the left point and the right point coordinates of the line enumeration sub-matrices. Row based on the left and right end points, maintenance of the sub-matrix with another monotonous minimum queue each row.

Code:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define pii pair<int, int>
#define LL long long
#define db double
using namespace std;
const int maxn = 3001;
pii q[maxn];
int l, r;
int q3[maxn][maxn], l3[maxn], r3[maxn];
int a[maxn][maxn];
int n, m;
void init(int p, int L, int R) {
	for (int j = L; j <= R; j++) {
		int tmp = a[p][j];
		while(l3[p] <= r3[p] && a[p][q3[p][r3[p]]] >= tmp) r3[p]--;
		q3[p][++r3[p]] = j;
	}
}
void maintain(int p, int L, int R) {
	int tmp = a[p][R];
	while(l3[p] <= r3[p] && q3[p][l3[p]] < L) l3[p]++;
	while(l3[p] <= r3[p] && a[p][q3[p][r3[p]]] >= tmp) r3[p]--;
	q3[p][++r3[p]] = R;
}
int query(int p) {
	return a[p][q3[p][l3[p]]];
}
int main() {
	int a1, b1, now, x, y, z;
	scanf("%d%d%d%d", &n, &m, &a1, &b1);
	scanf("%d%d%d%d", &now, &x, &y, &z);
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			a[i][j] = now;
			now = ((LL)now * x + y) % z;
		}
	}
	for (int i = 1; i <= n; i++) l3[i] = 1;
	LL ans = 0;
	for (int i = 1; i <= n; i++) {
		init(i, 1, b1 - 1);
	}
	for (int l1 = 1, r1 = b1; r1 <= m; l1++, r1++) {
		l = 1, r = 0;
		for (int j = 1; j <= a1; j++) {
			maintain(j, l1,r1);
			int tmp = query(j);
			while(l <= r && q[r].second >= tmp) r--;
			q[++r] = make_pair(j, tmp);
		}
		ans += q[l].second;
		for (int l2 = 2, r2 = a1 + 1; r2 <= n; l2++, r2++) {
			while(l <= r && q[l].first < l2) l++;
			maintain(r2, l1, r1);
			int tmp = query(r2);
			while(l <= r && q[r].second >= tmp) r--;
			q[++r] = make_pair(r2, tmp);
			ans += q[l].second;
		}
	}
	printf("%lld\n", ans);
}

  

 

Guess you like

Origin www.cnblogs.com/pkgunboat/p/11204846.html