Cod sursa(job #2067834)

Utilizator TincaMateiTinca Matei TincaMatei Data 16 noiembrie 2017 21:15:43
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.04 kb
#include <bits/stdc++.h>
 
using namespace std;
 
const int MAX_Q = 20000;
const int MAX_N = 300;
const int ITER = 17;
int rez[MAX_Q];
 
struct Query {
  int st, dr, mid;
  int l1, c1, l2, c2;
  int *r;
}v[MAX_Q];
 
pair<int, int> ord[MAX_N * MAX_N];
pair<int, int> sef[1+MAX_N][1+MAX_N];
int val[90000];

int matr[2+MAX_N][2+MAX_N];
int dl[4] = {0, 1, 0, -1};
int dc[4] = {1, 0, -1, 0};
 
bool cmp(Query a, Query b) {
  return a.mid > b.mid;
}
 
bool cmp2(pair<int, int> a, pair<int, int> b) {
  return matr[a.first][a.second] > matr[b.first][b.second];
}
 
pair<int, int> myfind(int l, int c) {
  if(sef[l][c].first == l && sef[l][c].second == c)
    return make_pair(l, c);
  sef[l][c] = myfind(sef[l][c].first, sef[l][c].second);
  return sef[l][c];
}
 
void myunion(int l1, int c1, int l2, int c2) {
  pair<int, int> sa = myfind(l1, c1), sb = myfind(l2, c2);
  if(sa != sb)
    sef[sa.first][sa.second] = sb;
}
 
bool sameset(int l1, int c1, int l2, int c2) {
  return myfind(l1, c1) == myfind(l2, c2);
}
 
int main() {
  int n, q, top = 0;
  FILE *fin = fopen("matrice2.in", "r");
  fscanf(fin, "%d%d", &n, &q);
  for(int l = 1; l <= n; ++l)
    for(int c = 1; c <= n; ++c) {
      fscanf(fin, "%d", &matr[l][c]);
      ord[top++] = make_pair(l, c);
    }
  for(int i = 0; i < q; ++i) {
    fscanf(fin, "%d%d%d%d", &v[i].l1, &v[i].c1, &v[i].l2, &v[i].c2);
    v[i].st = 0;
    v[i].r = &rez[i];
  }
  fclose(fin);
 
  for(int i = 0; i <= n + 1; ++i)
    matr[i][0] = matr[i][n + 1] = matr[n + 1][i], matr[0][i] = -1;
 
  sort(ord, ord + top, cmp2);
  int j = 0, last = matr[ord[0].first][ord[0].second];
  val[0] = last;
  for(int i = 0; i < top; ++i) {
    if(matr[ord[i].first][ord[i].second] == last)
      matr[ord[i].first][ord[i].second] = j;
    else {
      last = matr[ord[i].first][ord[i].second];
      matr[ord[i].first][ord[i].second] = ++j;
      val[j] = last;
    }
  }
  for(int i = 0; i < top; ++i)
    matr[ord[i].first][ord[i].second] = j - matr[ord[i].first][ord[i].second];
  for(int i = 0; i < (j + 1) / 2; ++i)
    val[i] ^= val[j-i] ^= val[i] ^= val[j-i];
  for(int i = 0; i < q; ++i)
    v[i].dr = j + 1;
  for(int it = 0; it < ITER; ++it) {
    int fc = 0;
    for(int i = 0; i < q; ++i)
      v[i].mid = (v[i].st + v[i].dr) / 2;
    sort(v, v + q, cmp);
    for(int l = 1; l <= n; ++l)
      for(int c = 1; c <= n; ++c)
        sef[l][c] = make_pair(l, c);
    for(int i = 0; i < q; ++i) {
      while(fc < top && matr[ord[fc].first][ord[fc].second] >= v[i].mid) {
        int l = ord[fc].first, c = ord[fc].second;
        for(int d = 0; d < 4; ++d) {
          int ln = l + dl[d], cn = c + dc[d];
          if(matr[ln][cn] >= v[i].mid)
            myunion(ln, cn, l, c);
        }
        ++fc;
      }
      if(sameset(v[i].l1, v[i].c1, v[i].l2, v[i].c2))
        v[i].st = v[i].mid;
      else
        v[i].dr = v[i].mid;
    }
  }
 
  for(int i = 0; i < q; ++i) {
    *v[i].r = v[i].st;
    assert(v[i].dr - v[i].st == 1);
  }
 
  FILE *fout = fopen("matrice2.out", "w");
  for(int i = 0; i < q; ++i)
    fprintf(fout, "%d\n", val[rez[i]]);
  fclose(fout);
  return 0;
}