Cod sursa(job #1696307)

Utilizator BrandonChris Luntraru Brandon Data 28 aprilie 2016 19:44:11
Problema Struti Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.91 kb
#include <fstream>
#include <cstring>

#define Pe pair <int, int>
#define mp make_pair
#define fi first
#define se second
using namespace std;

const int MaxN = 1005, MaxAltit = 8005, INF = 0x3f3f3f3f, MaxDqSz = 100005;

int mat[MaxN][MaxN], MinMat[MaxN][MaxN], MaxMat[MaxN][MaxN];
int n, m, p;

class Deque {
  int l, r, v[MaxDqSz];
public:
  Deque() {
    memset(v, 0, sizeof v);
    l = 1;
    r = 0;
  }

  inline void push_back(const int &x) {
    ++r;
    v[r] = x;
  }

  inline void pop_back() {
    --r;
  }

  inline void pop_front() {
    ++l;
  }

  inline int front() {
    return v[l];
  }

  inline int back() {
    return v[r];
  }

  inline int size() {
    return r - l + 1;
  }
};

Deque MaxDq, MinDq;

class InputReader {
public:
  InputReader() {}
  InputReader(const char *file_name) {
    input_file = fopen(file_name, "r");
    cursor = 0;
    fread(buffer, SIZE, 1, input_file);
  }
  inline InputReader &operator >>(int &n) {
    while (buffer[cursor] < '0' || buffer[cursor] > '9') {
      advance();
    }
    n = 0;
    while ('0' <= buffer[cursor] && buffer[cursor] <= '9') {
      n = n * 10 + buffer[cursor] - '0';
      advance();
    }
    return *this;
  }
private:
  FILE *input_file;
  static const int SIZE = 1 << 17;
  int cursor;
  char buffer[SIZE];
  inline void advance() {
    ++ cursor;
    if (cursor == SIZE) {
      cursor = 0;
      fread(buffer, SIZE, 1, input_file);
    }
  }
};

InputReader cin("struti.in");
ofstream cout("struti.out");

void PreCalc(int LineNr) {
  memset(MinMat, 0, sizeof MinMat);
  memset(MaxMat, 0, sizeof MaxMat);

  for (int j = 1; j <= m; ++j) {
    MaxDq = Deque();
    MinDq = Deque();

    for (int i = 1; i <= n; ++i) {
      while (MinDq.size() > 0 and MinDq.front() <= i - LineNr) {
        MinDq.pop_front();
      }

      while (MinDq.size() > 0 and mat[i][j] < mat[MinDq.back()][j]) {
        MinDq.pop_back();
      }

      MinDq.push_back(i);
      MinMat[i][j] = mat[MinDq.front()][j];

      while (MaxDq.size() > 0 and MaxDq.front() <= i - LineNr) {
        MaxDq.pop_front();
      }

      while (MaxDq.size() > 0 and mat[i][j] > mat[MaxDq.back()][j]) {
        MaxDq.pop_back();
      }

      MaxDq.push_back(i);
      MaxMat[i][j] = mat[MaxDq.front()][j];
    }
  }
}

Pe solve(int LineNr, int ColumnNr) {
  PreCalc(LineNr);
  int ans = INF;
  int cnt = 0;

  for (int i = LineNr; i <= n; ++i) {
    MaxDq = Deque();
    MinDq = Deque();

    for (int j = 1; j <= m; ++j) {
      while (MinDq.size() > 0 and MinDq.front() <= j - ColumnNr) {
        MinDq.pop_front();
      }

      while (MinDq.size() > 0 and MinMat[i][j] < MinMat[i][MinDq.back()]) {
        MinDq.pop_back();
      }

      MinDq.push_back(j);

      while (MaxDq.size() > 0 and MaxDq.front() <= j - ColumnNr) {
        MaxDq.pop_front();
      }

      while (MaxDq.size() > 0 and MaxMat[i][j] > MaxMat[i][MaxDq.back()]) {
        MaxDq.pop_back();
      }

      MaxDq.push_back(j);

      if (j >= ColumnNr) {
        int candidate = MaxMat[i][MaxDq.front()] - MinMat[i][MinDq.front()];

        if (candidate == ans) {
          ++cnt;
        }
        else if (candidate < ans) {
          ans = candidate;
          cnt = 1;
        }
      }
    }
  }

  return mp(ans, cnt);
}

int main() {
  cin >> n >> m >> p;

  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= m; ++j) {
      cin >> mat[i][j];
    }
  }

  for (int i = 1; i <= p; ++i) {
    int x, y;
    cin >> x >> y;

    Pe Ans;
    Pe Ans1 = solve(x, y);
    Pe Ans2;

    if (x != y) {
      Ans2 = solve(y, x);
    }
    else {
      Ans2 = mp(INF, INF);
    }

    if (Ans1.fi == Ans2.fi) {
      Ans = Ans1;
      Ans.se += Ans2.se;
    }
    else {
      Ans = min(Ans1, Ans2);
    }

    cout << Ans.fi << ' ' << Ans.se << '\n';
  }

  return 0;
}