Cod sursa(job #2813270)

Utilizator popoviciAna16Popovici Ana popoviciAna16 Data 6 decembrie 2021 10:55:59
Problema Matrice 2 Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.84 kb
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
using namespace std;

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

//aceasta solutie utilizeaza trucul de "cautare binara paralela";
//-> explicatia tehnicii: https://codeforces.com/blog/entry/45578

int a[302][302];

struct el
{
    int l, c, val;
} s[90001];

bool comp (const el &a, const el &b)
{
    return a.val > b.val;
}

struct idk
{
    int l1, c1, l2, c2;
    int cst, cdr, cmij;
} intr[20001];
//intr[i].cst, intr[i].cdr sunt capetele cautarii binare pentru intrebarea i,
//cu cst si cdr aratand valorile din s[] intre care se afla raspunsul pentru intrebarea i

vector <int> ver[90001];

int t[90001], h[90001];

int cauta (int x);
void uneste (int x, int y);

int main()
{
    int n, q, i, j, it, la, ca, lv, cv, x, y;
    int dl[4] = {-1, 0, 1, 0};
    int dc[4] = {0, 1, 0, -1};

    fin >> n >> q;
    for (i = 1; i<=n; i++)
        for (j = 1; j<=n; j++)
        {
            fin >> a[i][j];
            s[(i-1)*n + j] = {i, j, a[i][j]};
        }
    sort(s+1, s+n*n+1, comp);

    for (i = 1; i<=q; i++)
    {
        fin >> intr[i].l1 >> intr[i].c1 >> intr[i].l2 >> intr[i].c2;
        intr[i].cst = n*n;
        intr[i].cdr = 1;
    }

    for (it = 1; (1<<(it-1)) < n*n; it++)
    {
        for (i = 1; i<=n*n; i++)
        {
            t[i] = h[i] = 0;
            ver[i].clear();
        }

        for (i = 1; i<=q; i++)
            if (intr[i].cst >= intr[i].cdr)
            {
                intr[i].cmij = (intr[i].cst + intr[i].cdr) >> 1;
                ver[intr[i].cmij].push_back (i);
            }

        for (i = 1; i<=n*n; i++)
        {
            la = s[i].l;
            ca = s[i].c;
            for (j = 0; j<4; j++)
            {
                lv = la + dl[j];
                cv = ca + dc[j];
                if (lv >= 1 && lv <= n && cv >= 1 && cv <= n && a[lv][cv] >= s[i].val)
                {
                    x = cauta ((la-1)*n + ca);
                    y = cauta ((lv-1)*n + cv);
                    if (x != y)
                        uneste (x, y);
                }
            }

            for (j = 0; j<ver[i].size(); j++)
            {
                x = ver[i][j];
                if (cauta ((intr[x].l1-1)*n + intr[x].c1) == cauta ((intr[x].l2-1)*n + intr[x].c2))
                    intr[x].cst = intr[x].cmij - 1;
                else
                    intr[x].cdr = intr[x].cmij + 1;
            }
        }
    }

    for (i = 1; i<=q; i++)
        fout << s[intr[i].cdr].val << '\n';
    return 0;
}

int cauta (int x)
{
    int r = x, y;
    while (t[r])
        r = t[r];

    while (x != r)
    {
        y = t[x];
        t[x] = r;
        x = y;
    }
    return r;
}

void uneste (int x, int y)
{
    if (h[x] < h[y])
        t[x] = y;
    else
    {
        t[y] = x;
        if (h[x] == h[y])
            h[x]++;
    }
}