The input is an array (n*m 1<n,m< 1000). I have to find the maximum element in every sub-matrice of size( a*b ).
I was trying to do this by iterating x over n-a+1 and y over m-j+1.
2D segment trees or quad trees are not sufficiently fast as the number of queries is large.I tried to extend sparse table but was not able to due to shortage of space.
I have read about solutions with Cartesian trees but some code is needed as I cannot understand it.
Please explain a solution that will answer a query in O(nm) time or in O(1) time by pre-computation. Also, the input array is static.
Note: although I've tried sparse table, it might not have been correct, so feel free to post a solution with it.
I'm a Java coder, so an implementation in Java or c/c++ would be great.
Also this is not a duplicate as I have searched a lot about it without finding anything suitable.
(From Number of submatrix of size AxB in a matrix of size MxN)
In a matrix of size (m*n), there are (n-A+1)*(m-B+1) different matrices of size (A*B).
So the total number of possible input for your function is sum((n-A+1)*(m-B+1)) where A=1..n and B=1..m.
EDIT: This is getting so huge when m=1000.
O(m^2n^2)isO(1000^4)... 1 trillion ... this won't fit in my small computer's memory :)
I propose you build an hashmap that you simply index with the boundaries of your matrix:
A string built from a=M(i,j), b=M(k,l) where 0< i < k <(n+1) and 0< j < l <(m+1)
aHashMap("["+i+","+j+"].["+k+","+l+"]")Have a function that calculates the max of a given matrix (a[i,j],b[k,l]) - say myMax(i,j,k,l). I assume there is no point showing you how.
Then its easy (sorry I can't easily compile anything so I give only the principle for now):
for i=1 to n-1 do
for j=1 to m-1 do
for k=i to n do
for l=j to m do
aHashMap("["+i+","+j+"].["+k+","+l+"]") = myMax(i,j,k,l)
next
next
next
next
This is O(n^4), but assuming its pre-computational, there's no point, it just make your program bigger and bigger when storing aHashMap.
Such problem also seem to be widely addressed at http://cs.stackexchange.com ; e.g. this or that... so this SE could be of interest to the OP.
With 99 x 95 it already gives millions of possibilities to pre-compute, taking about 3Go RAM!
$ ./p1
enter number of rows:99
enter number of cols:95
pre-computing...
hashmap ready with 22572000 entries.
matrix.h
#ifndef myMatrix_JCHO
#define myMatrix_JCHO
typedef unsigned int u_it;
class Matrix
{
public:
Matrix(u_it _n, u_it _m);
Matrix(const Matrix& matr);
Matrix& operator=(const Matrix& matr);
~Matrix();
u_it getNumRows() ;
u_it getNumCols() ;
int getC(u_it i, u_it j);
void setC(u_it i, u_it j, int v);
void printMatrix();
int maxSub(u_it a_i, u_it a_j, u_it b_k, u_it b_l);
private:
u_it n, m;
int **pC;
};
#endif
matrix.cpp
#include <iostream>
#include <string>
#include <sstream>
#include "matrix.h"
Matrix::Matrix(u_it _n, u_it _m) {
n=_n;
m=_m;
int k=0;
pC = new int*[n];
for (u_it i=0; i<n; ++i){
pC[i]=new int[m];
for(u_it j=0; j<m; ++j){
pC[i][j]=++k;
}
}
}
Matrix::~Matrix(){
for (u_it i=0; i<n; ++i){
delete [] pC[i];
}
delete [] pC;
std::cout << "matrix destroyed\n";
}
u_it Matrix::getNumRows() {
return n;
}
u_it Matrix::getNumCols() {
return m;
}
int Matrix::getC(u_it i, u_it j){
return pC[i][j];
}
void Matrix::setC(u_it i, u_it j, int v){
pC[i][j]=v;
}
void Matrix::printMatrix(){
for (u_it i=0; i<n; ++i){
std::cout << "row " <<i<<" [ ";
for(u_it j=0; j<m; ++j){
std::cout << pC[i][j] << '\t';
}
std::cout << "]\n";
}
}
// Return max of submatrix a(i,j); b(k,l)
int Matrix::maxSub(u_it a_i, u_it a_j, u_it b_k, u_it b_l) {
int res = -100000;
if (a_i<=b_k && a_j<=b_l && b_k<n && b_l<m) {
for (u_it i=a_i; i<=b_k; ++i){
for(u_it j=a_j; j<=b_l; ++j){
res= (pC[i][j]>res)? pC[i][j] : res;
}
}
} else {
std::cout << "invalid arguments: out of bounds\n";
return -100000;
}
return res;
}
main.cpp
#include <iostream>
#include <string>
#include <sstream>
#include <map>
#include <cassert>
#include "matrix.h"
std::string hashKey(u_it a_i, u_it a_j, u_it b_k, u_it b_l) {
std::stringstream ss;
ss << "max(a[" << a_i << "," << a_j << "],b[" << b_k << "," << b_l << "]";
return ss.str();
}
int main() {
u_it n_rows, n_cols;
std::cout << " enter number of rows:";
std::cin >> n_rows;
std::cout << " enter number of cols:";
std::cin >> n_cols;
std::cout << " pre-computing...\n";
std::map<std::string, int> myHMap;
Matrix * mat=new Matrix(n_rows,n_cols);
//mat->printMatrix();
// "PRE" computation
for (u_it i=0; i<n_rows; ++i) {
for (u_it j=0; j<n_cols; ++j) {
for (u_it k=i; k<n_rows; ++k) {
for (u_it l=j; l<n_cols; ++l) {
//std::cout <<"max(a["<<i<<","<<j<<"],b["<<k<<","<<l<<"]"<< mat->maxSub(i, j, k, l) <<'\n';
//std::cout << mat->hashKey(i, j, k ,l) <<" -> " << mat->maxSub(i, j, k, l) <<'\n';
myHMap[hashKey(i, j, k ,l)] = mat->maxSub(i, j, k, l);
}
}
}
}
std::cout << " hashmap ready with "<< myHMap.size() <<" entries.\n";
// call to values
u_it cw_i, cw_j, cw_k, cw_l;
cw_i=0;
std::string hKey;
while (cw_i < n_rows+1) {
std::cout << " enter i,:";
std::cin >> cw_i;
std::cout << " enter j,:";
std::cin >> cw_j;
std::cout << " enter k,:";
std::cin >> cw_k;
std::cout << " enter l:";
std::cin >> cw_l;
hKey = hashKey(cw_i, cw_j, cw_k, cw_l);
std::map<std::string, int>::iterator i = myHMap.find(hKey);
assert(i != myHMap.end());
std::cout << i->first <<" -> " << i->second <<'\n';
}
}
make
g++ -std=c++0x -std=c++0x -Wall -c -g matrix.cpp
g++ -std=c++0x -std=c++0x -Wall -c -g main.cpp
g++ -std=c++0x -std=c++0x -Wall -g matrix.o main.o -o p1