Cod sursa(job #2963147)

Utilizator RobertAcAcatrinei Robert-Marian RobertAc Data 10 ianuarie 2023 10:29:54
Problema Matrice 2 Scor 75
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.43 kb
#include <bits/stdc++.h>

using namespace std;

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

const int qmax = 2e4 + 5;
const int nmax = 3e2 + 5;

struct query
{
    int ind, x1, y1, x2, y2;
    query(int ind = 0, int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0) : ind(ind), x1(x1), y1(y1), x2(x2), y2(y2) {}
};

struct queryNode
{
    int st, dr;
    int depth;
    vector<query *> queries;
    queryNode(vector<query *> queries, int st, int dr, int depth = 0) : queries(queries), st(st), dr(dr), depth(depth) {}
};

struct dijNode
{
    dijNode *p;
    int h;

    dijNode(int h = 0, dijNode *p = nullptr) : h(h), p(p) {}

    dijNode *getParent()
    {
        if (p == nullptr)
        {
            return this;
        }
        else
        {
            p = p->getParent();
            return p;
        }
    }

    bool sameTree(dijNode *other)
    {
        return (getParent() == other->getParent());
    }

    void unite(dijNode *other)
    {
        dijNode *pa = getParent();
        dijNode *pb = other->getParent();

        if (pa == pb)
            return;

        if (pa->h < pb->h)
        {
            pa->p = pb;
        }
        else if (pa->h > pb->h)
        {
            pb->p = pa;
        }
        else
        {
            pb->p = pa;
            pa->h++;
        }
    }

    void reset()
    {
        p = nullptr;
        h = 0;
    }
};

int v[nmax][nmax];                                 // harta
unordered_map<int, vector<pair<int, int>>> coords; // coordonatele unei valori
vector<int> vals;                                  // valori unice
int res[qmax];                                     // resultatul queriurilor
dijNode *nodes[nmax][nmax];                        // matrice de pointere catre noduri de multimi djuncte
int lastInd;
int diffx[] = {0, 1, 0, -1};
int diffy[] = {1, 0, -1, 0};
int n, q;

void uniteTill(int poz)
{
    for (int i = lastInd - 1; i >= poz; i--)
    {
        int val = vals[i]; // valoarea cautata
        for (auto j : coords[val])
        {
            auto tmpNode = nodes[j.first][j.second]; // nodul cu val
            for (int k = 0; k < 4; k++)
            {
                int x = j.first + diffx[k];
                int y = j.second + diffy[k];
                if (x >= 1 && x <= n && y >= 1 && y <= n)
                {
                    if (v[x][y] >= val)
                    {
                        tmpNode->unite(nodes[x][y]);
                    }
                }
            }
        }
    }
}

bool eval(query *q)
{
    return nodes[q->x1][q->y1]->sameTree(nodes[q->x2][q->y2]);
}

int main()
{
    in >> n >> q;
    set<int> s;

    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            in >> v[i][j];
            nodes[i][j] = new dijNode();
            coords[v[i][j]].push_back({i, j});
            s.insert(v[i][j]);
        }
    }

    for (auto i : s)
        vals.push_back(i);

    vector<query *> queries;

    for (int i = 0; i < q; i++)
    {
        int x1, y1, x2, y2;
        in >> x1 >> y1 >> x2 >> y2;
        queries.push_back(new query(i, x1, y1, x2, y2));
    }
    lastInd = vals.size();
    queue<queryNode> qq;
    qq.push(queryNode(queries, 0, vals.size() - 1));
    int lastDepth = vals.size();
    while (!qq.empty())
    {
        queryNode nod = qq.front();
        qq.pop();

        if (nod.st == nod.dr)
        {
            for (auto i : nod.queries)
            {
                res[i->ind] = vals[nod.st];
            }
        }
        else
        {
            int mid = (nod.st + nod.dr + 1) / 2;
            if (lastDepth != nod.depth)
            {
                lastInd = vals.size();
                lastDepth = nod.depth;
                for (int i = 1; i <= n; i++)
                {
                    for (int j = 1; j <= n; j++)
                    {
                        nodes[i][j]->reset();
                    }
                }
            }

            uniteTill(mid);
            lastInd = mid;

            vector<query *> st, dr;

            for (auto i : nod.queries)
            {
                if (eval(i))
                {
                    dr.push_back(i);
                }
                else
                {
                    st.push_back(i);
                }
            }
            qq.push(queryNode(dr, mid, nod.dr, nod.depth + 1));
            qq.push(queryNode(st, nod.st, mid - 1, nod.depth + 1));
        }
    }

    for (int i = 0; i < q; i++)
    {
        out << res[i] << '\n';
    }
}