1

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.

4

2 に答える 2

0

計算するための答えを見つけましたO(mn)-まだ少し事前計算があります-しかし、今回は最後のものも簡単O(mn.log(mn))です.すべての行列の値のリストを並べ替えるだけです.

事前計算:

最初のステップは、行列の値の整然とした構造を単純に構築することです。たとえばM(A)、 を使用<algorithm>std::sortして、その構造を順序付けます。

任意のサブマトリックスの最大値を取得(a,b):

行列の最大値を取得するには、事前に計算された構造から最大のものから始めて、M(A)それが 内にあるかどうかを確認します(a,b)

  • もしそうなら、あなたは終わった
  • そうでなければ、次のものを取りますM(A)

マトリックス.h

#ifndef myMatrix_JCHO
#define myMatrix_JCHO

typedef unsigned int u_it;
typedef std::pair<u_it, u_it> uup;

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

マトリックス.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]=rand()%1000;
       }
    }
}
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";
    }
}

main.cpp

#include <iostream>
#include <string>
#include <utility>
#include <algorithm>
#include <vector>

#include "matrix.h"


// sort function for my vector of pair:
bool oMyV(std::pair<uup, int> x, std::pair<uup, int> y) { return (x.second > y.second); }

// check that p is within matrix formed by a and b
bool isIn_a_b(uup p, uup a, uup b){
    bool res = false;
    if (p.first >= a.first && p.first <= b.first) {
      if (p.second >= a.second && p.second <= b.second) {
        res = true;
      }
    }
    return res;
}

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::pair<uup, int> *ps;
    std::vector<std::pair<uup, int> > myV;
    Matrix * mat=new Matrix(n_rows,n_cols);
    // print to debug:
    mat->printMatrix();
    // "PRE" computation
    for (u_it i=0; i<n_rows; ++i) {
      for (u_it j=0; j<n_cols; ++j) {
        ps=new std::pair<uup, int>(std::make_pair(i,j), mat->getC(i,j));
        myV.push_back(*ps);
      }
    }
    std::sort(myV.begin(), myV.end(), oMyV);
    /* in case you want to print ordered valuet ordered valuess for debug */
    for (std::vector<std::pair<uup, int> >::iterator it=myV.begin(); it!=myV.end(); ++it) {
      std::cout << it->second << " at [" << it->first.first <<','<<it->first.second<< "]\n";
    }
    /**/

    // call to values
    bool byebye=false;
    uup a, b;

    do {
      std::cout << " enter i,:";     std::cin >> a.first;
      std::cout << " enter j,:";     std::cin >> a.second;
      std::cout << " enter k,:";     std::cin >> b.first;
      std::cout << " enter l,:";     std::cin >> b.second;

      std::vector<std::pair<uup, int> >::iterator it=myV.begin();
      std::cout << " a:["<<a.first<<','<<a.second<<"]-b:["<<b.first<<','<<b.second<<"] in ";
      std::cout << " M:[0,0]--:["<<n_rows-1<<','<<n_cols-1<<"]\n";
      // check validity:
      if (  isIn_a_b(a, std::make_pair(0,0), std::make_pair(n_rows-1, n_cols-1) )
         && isIn_a_b(b, std::make_pair(0,0), std::make_pair(n_rows-1, n_cols-1) )
         && (a.first <= b.first)
         && (a.second <= b.second)
         ) {
        while (! isIn_a_b(it->first, a, b) && it!=myV.end()){
          ++it;
        }
        std::cout << "Found:" << it->second << " at [" << it->first.first <<','<<it->first.second<< "]\n";
      } else {
        std::cout << "makes no sense. bye.\n";
        byebye=true;
      }
    } while (!byebye);
}

メイクファイル

(忘れないでください: Makefile で集計します)

OBJS = matrix.o main.o
CC = g++ -std=c++0x
DEBUG = -g
CFLAGS = -std=c++0x -Wall -c $(DEBUG)
LFLAGS = -std=c++0x -Wall $(DEBUG)
TARFILE =  ${HOME}/jcho/good/matrix.tar

p1 : $(OBJS)
        $(CC) $(LFLAGS) $(OBJS) -o p1

matrix.o: matrix.cpp matrix.h
        $(CC) $(CFLAGS) matrix.cpp

main.o: main.cpp matrix.h
        $(CC) $(CFLAGS) main.cpp

clean:
        \rm -f *.o *~ p1

tar:
        tar cfv  $(TARFILE) *.h *.cpp Makefile \
            p1 && \
            echo "tar $(TARFILE) created successfuly."
于 2016-06-29T12:34:40.763 に答える