Cod sursa(job #2017102)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 31 august 2017 11:59:07
Problema Struti Scor 100
Compilator cpp Status done
Runda Teme Pregatire ACM Unibuc 2013 Marime 4.27 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 MAXBUF = 6000000;
char input_buf[MAXBUF], *input_head;
bool numeric[256];

void parserInit() {
  int end = fread(input_buf, 1, MAXBUF, stdin);
  input_buf[end] = 0;
  input_head = input_buf;
  memset(numeric, 0, sizeof(numeric));
  for (int i = '0'; i <= '9'; ++i)
    numeric[i] = true;
}

int nextInt() {
  int ans = 0;
  for (; !numeric[*input_head]; ++input_head);
  for (; numeric[*input_head]; ++input_head)
    ans = ans * 10 + (*input_head) - '0';
  return ans;
}

const int MAXN = 1010, MAXLOG = 10;
short a[MAXN][MAXN];
short pre[MAXN][MAXN][MAXLOG];
int N, M, Q, nextk; int id_global;

void rmq_advance(int llim) {
  int k = nextk;

  for (int i = N; i >= 1; --i)
  for (int j = M; j >= 1; --j) {
    if (k == 0)
      pre[i][j][0] = a[i][j];
    else {
      int aux = i - (1 << (k - 1));
      if (aux >= 1 && pre[aux][j][0] > pre[i][j][0])
        pre[i][j][0] = pre[aux][j][0];
    }
  }

  for (int i = 1; i <= N; ++i)
  for (int j = 1; j <= M; ++j) {
    for (int l = 1; l <= llim; ++l) {
      pre[i][j][l] = pre[i][j][l - 1];
      int aux = j - (1 << (l - 1));
      if (aux >= 1 && pre[i][aux][l - 1] > pre[i][j][l])
        pre[i][j][l] = pre[i][aux][l - 1];
    }
  }
}

int logtable[MAXN];

void precomputeLogs() {
  int cur = 0;
  for (int i = 1; i < MAXN; ++i) {
    if ((1 << (cur + 1)) <= i)
      ++cur;
    logtable[i] = cur;
  }
}

inline int LOG2(int x) {
  return logtable[x];
}

#define RELAX() if(cand > best) best = cand;

int rmq(int i1, int j1, int i2, int j2) {
  int Li = LOG2(i2 - i1), Lj = LOG2(j2 - j1);
  int ii = i1 + (1 << Li) - 1, jj = j1 + (1 << Lj) - 1;
  short best = pre[ii][jj][Lj];
  short cand = pre[i2][jj][Lj]; RELAX();
  cand = pre[ii][j2][Lj]; RELAX();
  cand = pre[i2][j2][Lj]; RELAX();
  return (int)best;
}

vector<int> tmpres[25];
pair<int, int> qres[25]; int qind[MAXN];

void calc1(int dx, int dy, int qid) {
  for (int i1 = 1, i2 = i1 + dx - 1; i2 <= N; ++i1, ++i2)
  for (int j1 = 1, j2 = j1 + dy - 1; j2 <= M; ++j1, ++j2) {
    int res = rmq(i1, j1, i2, j2);
    if (id_global == 0) {
      tmpres[qid].push_back(res);
      continue;
    }
    int aux = res + tmpres[qid][qind[qid]++];
    if (aux < qres[qid].first) {
      qres[qid].first = aux;
      qres[qid].second = 0;
    }
    if (aux == qres[qid].first)
      ++qres[qid].second;
  }
}

typedef pair< pair<short, short>, int > query;
vector<query> queries;

bool cmp(const query &a, const query &b) {
  int xa = LOG2(a.first.first - 1), xb = LOG2(b.first.first - 1);
  if (xa != xb)
    return xa < xb;
  xa = LOG2(a.first.second - 1), xb = LOG2(b.first.second - 1);
  if (xa != xb)
    return xa > xb;
  return a < b;
}

void solveOnce() {
  nextk = 0;
  for (const auto &it : queries) {
    int lim1 = LOG2(it.first.first - 1), lim2 = LOG2(it.first.second - 1);
    for (; nextk <= lim1; ++nextk)
      rmq_advance(lim2);
    calc1(it.first.first, it.first.second, it.second);
  }
  ++id_global;
}

void input() {
  N = nextInt(); M = nextInt(); Q = nextInt();
  for (int i = 1; i <= N; ++i)
  for (int j = 1; j <= M; ++j)
    a[i][j] = (short)nextInt();
  for (int i = 0; i < Q; ++i) {
    qres[i].first = INT_MAX;
    short dx = (short)nextInt(), dy = (short)nextInt();
    queries.push_back(make_pair(make_pair(dx, dy), i));
    if (dx != dy)
      queries.push_back(make_pair(make_pair(dy, dx), i));
  }
}

int main() {
  assert(freopen(InFile, "r", stdin));
  assert(freopen(OuFile, "w", stdout));
  parserInit();
  precomputeLogs();
  input();
  sort(queries.begin(), queries.end(), cmp);
  solveOnce();
  for (int i = 1; i <= N; ++i)
  for (int j = 1; j <= M; ++j)
    a[i][j] = -a[i][j];
  solveOnce();
  for (int i = 0; i < Q; ++i)
    printf("%d %d\n", qres[i].first, qres[i].second);
  return 0;
}