Cod sursa(job #2755523)

Utilizator GabiTulbaGabi Tulba-Lecu GabiTulba Data 27 mai 2021 16:19:44
Problema Matrice 2 Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.13 kb
#include <cmath>

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <vector>

#include <queue>

#define INF 2140000000

#define MaxN 305

#define MaxQ 200000

#define pi 3.1415926535897932384626433832795

using namespace std;

FILE *IN, *OUT;

int N, Q, Last[MaxQ], Max = 0, pos = 0;

struct spec

{

    int fx, fy, value;

} Mat[MaxN][MaxN];

struct spec2

{

    int value, x, y;

} l[MaxN * MaxN];

struct query

{

    int x1, y1, x2, y2, pos;
};

vector<query> Quest;

bool cond(spec2 a, spec2 b)

{

    return a.value > b.value;
}

queue<pair<pair<int, int>, vector<query>>> Queue;

void Reinitialize()

{

    pos = 0;

    for (int i = 1; i <= N; i++)

        for (int j = 1; j <= N; j++)

            Mat[i][j].fx = i, Mat[i][j].fy = j;
}

pair<int, int> find(int x, int y)

{

    pair<int, int> orig;

    orig.first = x, orig.second = y;

    while (Mat[x][y].fx != x || Mat[x][y].fy != y)

    {

        int ax = Mat[x][y].fx, ay = Mat[x][y].fy;

        x = ax, y = ay;
    }

    while (orig.first != x || orig.second != y)

    {

        int ax = Mat[orig.first][orig.second].fx,
            ay = Mat[orig.first][orig.second].fy;

        Mat[orig.first][orig.second].fx = x;

        Mat[orig.first][orig.second].fy = y;

        orig.first = ax, orig.second = ay;
    }

    return make_pair(x, y);
}

void Add(spec2 point)

{

    int X = point.x, Y = point.y, V = point.value;

    if (Mat[X][Y].fx != X || Mat[X][Y].fy != Y)

        return;

    if (X > 1 && Mat[X - 1][Y].value >= V)

    {

        pair<int, int> f = find(X - 1, Y);

        Mat[f.first][f.second].fx = X;

        Mat[f.first][f.second].fy = Y;
    }

    if (Y > 1 && Mat[X][Y - 1].value >= V)

    {

        pair<int, int> f = find(X, Y - 1);

        Mat[f.first][f.second].fx = X;

        Mat[f.first][f.second].fy = Y;
    }

    if (X < N && Mat[X + 1][Y].value >= V)

    {

        pair<int, int> f = find(X + 1, Y);

        Mat[f.first][f.second].fx = X;

        Mat[f.first][f.second].fy = Y;
    }

    if (Y < N && Mat[X][Y + 1].value >= V)

    {

        pair<int, int> f = find(X, Y + 1);

        Mat[f.first][f.second].fx = X;

        Mat[f.first][f.second].fy = Y;
    }
}

int main() {

    IN = fopen("matrice2.in", "r");

    OUT = fopen("matrice2.out", "w");

    fscanf(IN, "%d%d", &N, &Q);

    for (int i = 1; i <= N; i++)

        for (int j = 1; j <= N; j++)

        {

            fscanf(IN, "%d", &Mat[i][j].value);

            Mat[i][j].fx = i;

            Mat[i][j].fy = j;

            l[(i - 1) * N + j].value = Mat[i][j].value;

            l[(i - 1) * N + j].x = i;

            l[(i - 1) * N + j].y = j;

            Max = max(Max, Mat[i][j].value);
        }

    sort(l + 1, l + 1 + N * N, cond);

    for (int i = 1; i <= Q; i++)

    {

        query aux;

        fscanf(IN, "%d%d%d%d", &aux.x1, &aux.y1, &aux.x2, &aux.y2);

        aux.pos = i;

        Quest.push_back(aux);
    }

    l[0].value = INF;

    Queue.push(make_pair(make_pair(Max, 0), Quest));

    while (!Queue.empty())

    {

        int L = Queue.front().first.first;

        int R = Queue.front().first.second;

        int Mid = (R + L) >> 1;

        vector<query> left, right;

        if (l[pos].value < Mid)

            Reinitialize();

        while (l[pos + 1].value > Mid)

            Add(l[++pos]);

        for (int i = 0; i < Queue.front().second.size(); i++)

        {

            query aux = Queue.front().second[i];

            if (find(aux.x1, aux.y1) == find(aux.x2, aux.y2))

                left.push_back(aux);

            else
                right.push_back(aux);
        }

        if (L - R <= 1)

        {

            for (int i = 0; i < left.size(); i++)

                Last[left[i].pos] = L;

            for (int i = 0; i < right.size(); i++)

                Last[right[i].pos] = R;

        }

        else

        {

            if (!left.empty())

                Queue.push(make_pair(make_pair(L, Mid + 1), left));

            if (!right.empty())

                Queue.push(make_pair(make_pair(Mid, R), right));
        }

        Queue.pop();
    }

    for (int i = 1; i <= Q; i++)

        fprintf(OUT, "%d\n", Last[i]);

    return 0;
}