Colmerauer
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 276 Accepted Submission(s): 118
Problem Description
Peter has an
n×m
matrix
M
. Let
S(a,b)
be the sum of the weight all
a×b
submatrices of
M
. The weight of matrix is the sum of the value of all the saddle points in the matrix. A saddle point of a matrix is an element which is both the only largest element in its column and the only smallest element in its row. Help Peter find out all the value of
S(a,b)
.
Note: the definition of saddle point in this problem may be different with the definition you knew before.
Note: the definition of saddle point in this problem may be different with the definition you knew before.
Input
There are multiple test cases. The first line of input contains an integer
T
, indicating the number of test cases. For each test case:
The first contains two integers n and m (1≤n,m≤1000) -- the dimensions of the matrix.
The next n lines each contain m non-negative integers separated by spaces describing rows of matrix M (each element of M is no greater than 106 ).
The first contains two integers n and m (1≤n,m≤1000) -- the dimensions of the matrix.
The next n lines each contain m non-negative integers separated by spaces describing rows of matrix M (each element of M is no greater than 106 ).
Output
For each test case, output an integer
W=(∑a=1n∑b=1ma⋅b⋅S(a,b)) mod 232
.
Sample Input
3 2 2 1 1 1 1 3 3 1 2 3 4 5 6 7 8 9 3 3 1 2 1 2 3 1 4 5 2
Sample Output
4 600 215
Source
对于矩阵种一个元素M(x,y)考虑他可以成为那些子矩阵的鞍点, 用单调队列之类的东西处理出a,b,c,d, 分别表示在第x行中, 这个元素在第y−a列到y+b列中都是唯一最小值; 第y列中, 这个元素在第x−c到x+d行中都是唯一最大值.
对于公式, 只需要推导下这个元素对整体式子的贡献就好了.
#include <map>
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define uint unsigned int
using namespace std;
const int MAXN = 1e3 + 5;
int L[MAXN][MAXN], R[MAXN][MAXN], U[MAXN][MAXN], D[MAXN][MAXN];
int n, m, O[MAXN][MAXN], T;
//L[i][j]代表满足条件的左边端点
int sta[MAXN];
uint cal(int l, int x, int r) {
uint a = r - x + 1;
uint b = x - l + 1;
return a * (a + 1) / 2 * b + b * (b - 1) / 2 * a;
}
int main() {
while(~scanf("%d", &T)) {
while(T --) {
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i ++) {
for(int j = 0; j < m; j ++) {
scanf("%d", &O[i][j]);
}
}
int top = 0;
for(int i = 0; i < n; i ++) {
top = 0;
for(int j = 0; j < m; j ++) {
while(top && O[i][sta[top - 1]] > O[i][j]) top --;
if(top == 0) L[i][j] = 0;
else L[i][j] = sta[top - 1] + 1;
sta[top ++] = j;
}
top = 0;
for(int j = m - 1; j >= 0; j --) {
while(top && O[i][sta[top - 1]] > O[i][j]) top --;
if(top == 0) R[i][j] = m - 1;
else R[i][j] = sta[top - 1] - 1;
sta[top ++] = j;
}
}
for(int i = 0; i < m; i ++) {
top = 0;
for(int j = 0; j < n; j ++) {
while(top && O[sta[top - 1]][i] < O[j][i]) top --;
if(top == 0) U[j][i] = 0;
else U[j][i] = sta[top - 1] + 1;
sta[top ++] = j;
}
top = 0;
for(int j = n - 1; j >= 0; j --) {
while(top && O[sta[top - 1]][i] < O[j][i]) top --;
if(top == 0) D[j][i] = n - 1;
else D[j][i] = sta[top - 1] - 1;
sta[top ++] = j;
}
}
uint ret = 0;
for(int i = 0; i < n; i ++) {
for(int j = 0; j < m; j ++) {
ret += (uint)O[i][j] * cal(L[i][j], j, R[i][j]) * cal(U[i][j], i, D[i][j]);
}
}
printf("%u\n", ret);
}
}
return 0;
}