Cod sursa(job #1734780)

Utilizator BrandonChris Luntraru Brandon Data 28 iulie 2016 11:28:06
Problema Matrice 2 Scor 10
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.08 kb
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

ifstream cin("matrice2.in");
ofstream cout("matrice2.out");

const int MaxN = 905;
const int dir[4][2] = {{0, -1}, {-1, 0}, {0, 1}, {1, 0}};

int father[MaxN], depth[MaxN], mat[MaxN][MaxN];
int n, q, N;

class m_p {
public:
  int pos1, pos2, ans, ind;
  m_p(int _pos1 = 0, int _pos2 = 0, int _ans = 0, int _ind = 0) {
    pos1 = _pos1;
    pos2 = _pos2;
    ans = _ans;
    ind = _ind;
  }

  inline bool operator < (const m_p &other) const {
    return ans > other.ans;
  }
};

vector <m_p> Qry;

class m_v {
public:
  int val, x, y;
  m_v(int _val = 0, int _x = 0, int _y = 0) {
    val = _val;
    x = _x;
    y = _y;
  }

  inline bool operator < (const m_v &other) const {
    return val > other.val;
  }
};

vector <m_v> v;

void DSUInit() {
  for (int i = 1; i <= N; ++i) {
    father[i] = -1;
    depth[i] = 1;
  }
}

int FindRt(int node) {
  if (father[node] == node) {
    return node;
  }

  return father[node] = FindRt(father[node]);
}

void DSUMerge(int node1, int node2) {
  int Rt1 = FindRt(node1);
  int Rt2 = FindRt(node2);

  if (depth[Rt1] < depth[Rt2]) {
    father[Rt1] = Rt2;
  }
  else if (depth[Rt2] < depth[Rt1]) {
    father[Rt2] = Rt1;
  }
  else {
    father[Rt2] = Rt1;
    ++depth[Rt1];
  }
}

inline bool cmp(const m_p &a, const m_p &b) {
  return a.ind < b.ind;
}

inline bool InBound(const int &x, const int &y) {
  return x >= 1 and x <= n and y >= 1 and y <= n;
}

int main() {
  cin >> n >> q;
  N = n * n;

  for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= n; ++j) {
      int x;
      cin >> x;
      v.push_back(m_v(x, i, j));
    }
  }

  for (int i = 1; i <= (int) v.size(); ++i) {
    mat[v[i - 1].x][v[i - 1].y] = i;
  }

  for (int i = 1; i <= q; ++i) {
    int a, b;
    cin >> a >> b;
    int pos1 = mat[a][b];
    cin >> a >> b;
    int pos2 = mat[a][b];

    Qry.push_back(m_p(pos1, pos2, 0, i));
  }

  sort(v.begin(), v.end());
  for (int pow = 20; pow >= 0; --pow) {
    DSUInit();
    sort(Qry.begin(), Qry.end());
    auto itQ = Qry.begin();

    for (auto itV: v) {
      while (itQ < Qry.end() and itQ->ans + (1 << pow) > itV.val) {
        if (father[itQ->pos1] != -1 and father[itQ->pos2] != -1 and FindRt(itQ->pos1) == FindRt(itQ->pos2)) {
          itQ->ans += (1 << pow);
        }
        ++itQ;
      }

      father[mat[itV.x][itV.y]] = mat[itV.x][itV.y];
      for (int iDir = 0; iDir < 4; ++iDir) {
        int NewX = itV.x + dir[iDir][0];
        int NewY = itV.y + dir[iDir][1];
        if (InBound(NewX, NewY) and father[mat[NewX][NewY]] != -1) {
          DSUMerge(mat[itV.x][itV.y], mat[NewX][NewY]);
        }
      }
    }

    while (itQ < Qry.end()) {
      if (father[itQ->pos1] != -1 and father[itQ->pos2] != -1 and FindRt(itQ->pos1) == FindRt(itQ->pos2)) {
        itQ->ans += (1 << pow);
      }

      ++itQ;
    }
  }

  sort(Qry.begin(), Qry.end(), cmp);
  for (auto itQ: Qry) {
    cout << itQ.ans << '\n';
  }
  return 0;
}