Cod sursa(job #2596623)

Utilizator trifangrobertRobert Trifan trifangrobert Data 10 aprilie 2020 02:47:35
Problema Matrice 2 Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.81 kb
#include <bits/stdc++.h>

using namespace std;

const int NMAX = 301;
const int QMAX = 20001;
const int MAX = 1000001;

struct Query
{
    int x1, y1, x2, y2;
    int left, right, mid, answer;
    bool solved;
};

struct Value
{
    int val, i, j;
};

int N, Q, M;
int a[NMAX][NMAX];
Query q[QMAX];
bool found[QMAX];
Value vals[NMAX * NMAX];
int root[NMAX * NMAX];
bool dsu[NMAX][NMAX];
int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};
int diff[NMAX * NMAX];
vector <int> ind[NMAX * NMAX];
map <int, int> valtopos;

bool Inside(int i, int j)
{
    return 1 <= i && i <= N && 1 <= j && j <= N;
}

int Convert(int i, int j)
{
    return (i - 1) * N + j;
}



void Union(int x, int y)
{
    if (rand() % 2)
        root[y] = x;
    else
        root[x] = y;
}

int Find(int x)
{
    int r = x, cx;
    while (root[r] != 0)
        r = root[r];
    while (x != r)
    {
        cx = root[x];
        root[x] = r;
        x = cx;
    }
    return r;
}

int main()
{
    srand(time(NULL));
    ifstream fin("matrice2.in");
    ofstream fout("matrice2.out");
    fin >> N >> Q;
    for (int i = 1;i <= N;++i)
        for (int j = 1;j <= N;++j)
        {
            fin >> a[i][j];
            vals[(i - 1) * N + j] = {a[i][j], i, j};
            diff[(i - 1) * N + j] = a[i][j];
        }
    sort(diff + 1, diff + N * N + 1);
    for (int i = 1, jumpi = 1;i <= N * N;i = jumpi)
    {
        while (jumpi <= N * N && diff[jumpi] == diff[i])
            ++jumpi;
        diff[++M] = diff[i];
        valtopos[diff[i]] = M;
    }
    sort(vals + 1, vals + N * N + 1, [&](Value x, Value y)
    {
        return x.val < y.val;
    });
    for (int i = 1;i <= Q;++i)
    {
        int x1, y1, x2, y2;
        fin >> x1 >> y1 >> x2 >> y2;
        q[i] = {x1, y1, x2, y2, 1, M, M / 2, 0};
    }
    int solved = 0;
    while (solved < Q)
    {
        solved = 0;
        for (int i = 1;i <= Q;++i)
        {
            q[i].mid = (q[i].left + q[i].right) / 2;
            ind[q[i].mid].push_back(i);
        }
        for (int i = N * N;i >= 1;--i)
        {
            int x, y, a, b;
            for (int j = 0;j < 4;++j)
            {
                x = vals[i].i + dx[j];
                y = vals[i].j + dy[j];
                if (Inside(x, y) && dsu[x][y] == true)
                {
                    a = Find(Convert(vals[i].i, vals[i].j));
                    b = Find(Convert(x, y));
                    if (a != b)
                        Union(a, b);
                }
            }
            if (vals[i].val != vals[i - 1].val)
            {
                int aux = valtopos[vals[i].val];
                for (auto& j : ind[aux])
                {
                    Query qq = q[j];
                    a = Find(Convert(qq.x1, qq.y1));
                    b = Find(Convert(qq.x2, qq.y2));
                    if (a == b)
                        found[j] = true;
                    else
                        found[j] = false;
                }
            }
            dsu[vals[i].i][vals[i].j] = true;
        }
        for (int i = 1;i <= Q;++i)
        {
            if (found[i] == true)
            {
                q[i].left = q[i].mid + 1;
                q[i].answer = diff[q[i].mid];
            }
            else
                q[i].right = q[i].mid - 1;
            if (q[i].right < q[i].left)
                ++solved;
            found[i] = false;
        }
        for (int i = 1;i <= N;++i)
            for (int j = 1;j <= N;++j)
                dsu[i][j] = false;
        for (int i = 1;i <= N * N;++i)
        {
            root[i] = 0;
            ind[i].clear();
        }

    }
    for (int i = 1;i <= Q;++i)
        fout << q[i].answer << "\n";
    fin.close();
    fout.close();
    return 0;
}