Cod sursa(job #2016878)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 30 august 2017 19:05:16
Problema Struti Scor 30
Compilator cpp Status done
Runda Teme Pregatire ACM Unibuc 2013 Marime 3.55 kb
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <cassert>
#include <cstring>
#include <climits>
#include <queue>
using namespace std;
typedef long long LL;

#ifdef INFOARENA
#define ProblemName "struti"
#endif

#define MCONCAT(A, B) A B
#ifdef ProblemName
#define InFile MCONCAT(ProblemName, ".in")
#define OuFile MCONCAT(ProblemName, ".out")
#else
#define InFile "fis.in"
#define OuFile "fis.out"
#endif

const int MAXN = 1050;
int a[2][MAXN][MAXN];
int pre[2][MAXN][MAXN];
int N, M, Q;
int arbSz;
int arbInt[2][MAXN][MAXN * 2];

inline int parent(int x) {
  return ((x - 1) >> 1);
}

inline int leftSon(int x) {
  return x * 2 + 1;
}

inline int rightSon(int x) {
  return x * 2 + 2;
}

void makeArb(int id, int line) {
  arbInt[id][line][arbSz - 1] = INT_MIN;
  for (int j = 1; j <= M; ++j)
    arbInt[id][line][arbSz - 1 + j] = a[id][line][j];
  for (int j = arbSz + M; j < 2 * arbSz; ++j)
    arbInt[id][line][j] = INT_MIN;
  for (int j = arbSz - 2; j >= 0; --j)
    arbInt[id][line][j] = max(arbInt[id][line][leftSon(j)], arbInt[id][line][rightSon(j)]);
}

int query(int *arb, int left, int right) {
  left += arbSz - 1;
  right += arbSz - 1;
  int best = arb[left++];
  while (left <= right) {
    if (arb[left] > best) best = arb[left];
    if (arb[right] > best) best = arb[right];
    left = parent(left + 1);
    right = parent(right - 1);
  }
  return best;
}

void rmq_init(int id) {
  for (int i = 0; i <= N; ++i)
  for (int j = 0; j <= N; ++j) {
    if (i == 0 || j == 0) {
      pre[id][i][j] = INT_MIN;
      continue;
    }
    pre[id][i][j] = a[id][i][j];
    if (pre[id][i - 1][j] > pre[id][i][j])
      pre[id][i][j] = pre[id][i - 1][j];
    if (pre[id][i][j - 1] > pre[id][i][j])
      pre[id][i][j] = pre[id][i][j - 1];
  }
  for (arbSz = 1; arbSz <= N; arbSz *= 2);
  for (int i = 1; i <= N; ++i)
    makeArb(id, i);
}

int maxOnLine(int id, int i, int j1, int j2) {
  /*int best = INT_MIN;
  for (int j = j1; j <= j2; ++j)
  if (a[id][i][j] > best)
    best = a[id][i][j];
  return best;*/
  return query(arbInt[id][i], j1, j2);
}

int rmq(int id, int i1, int j1, int i2, int j2) {
  int best = INT_MIN;
  for (int i = i2; i >= i1; --i) {
    int bestHere = pre[id][i][j2];
    if (bestHere <= best)
      return best;
    if (bestHere != pre[id][i][j1 - 1] && bestHere != pre[id][i1 - 1][j2])
      return bestHere;
    int maxi = maxOnLine(id, i, j1, j2);
    if (maxi == bestHere)
      return bestHere;
    if (maxi > best)
      best = maxi;
  }
  return best;
}

void calc1(int dx, int dy, int &best, int &nr) {
  for (int i1 = 1, i2 = i1 + dx - 1; i2 <= N; ++i1, ++i2)
  for (int j1 = 1, j2 = j1 + dy - 1; j2 <= M; ++j1, ++j2) {
    //printf("Considering (%d %d) (%d %d)", i1, j1, i2, j2);
    int res = rmq(0, i1, j1, i2, j2) + rmq(1, i1, j1, i2, j2);
    //printf(" -- result %d\n", res);
    if (res < best) {
      best = res;
      nr = 0;
    }
    if (res == best)
      ++nr;
  }
}

void input() {
  scanf("%d%d%d", &N, &M, &Q);
  for (int i = 1; i <= N; ++i)
  for (int j = 1; j <= M; ++j) {
    if (N <= M) {
      scanf("%d", &a[0][i][j]);
      a[1][i][j] = -a[0][i][j];
    }
    else {
      scanf("%d", &a[0][j][i]);
      a[1][j][i] = -a[0][j][i];
    }
  }
  if (N > M)
    swap(N, M);
}

int main() {
  assert(freopen(InFile, "r", stdin));
  assert(freopen(OuFile, "w", stdout));
  input();
  rmq_init(0), rmq_init(1);
  while (Q--) {
    int dx, dy;
    scanf("%d%d", &dx, &dy);
    int best = INT_MAX, nr = 0;
    calc1(dx, dy, best, nr);
    if (dx != dy)
      calc1(dy, dx, best, nr);    
    printf("%d %d\n", best, nr);
  }
  return 0;
}