Cod sursa(job #2074144)

Utilizator Coroian_DavidCoroian David Coroian_David Data 24 noiembrie 2017 09:43:42
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.47 kb
#include <bits/stdc++.h>

#define MAX_N 300
#define MAX_Q 20000
#define MAX_DIR 4

using namespace std;

FILE *f, *g;

int n, q;

struct nrul
{
    int x, cod;
};

nrul nr[MAX_N * MAX_N + 1];

struct elem
{
    int x, y, i, rez;
};

elem v[MAX_Q + 1];

struct query
{
    int nr, i;
    int ok;
};

query que[MAX_Q + 1];

struct cmpNR
{
    bool operator () (const nrul &a, const nrul &b) const
    {
        return a.x > b.x;
    }
};

struct cmpQ
{
    bool operator () (const query &a, const query &b) const
    {
        return a.nr > b.nr;
    }
};

const int dl[] = {-1, 1, 0, 0};
const int dc[] = {0, 0, -1, 1};

int a[MAX_N  * MAX_N + 1];
int lin[MAX_N * MAX_N + 1];
int comp[MAX_N * MAX_N + 1];
int h[MAX_N * MAX_N + 1];

struct cmpI
{
    bool operator () (const elem &a, const elem &b) const
    {
        return a.i < b.i;
    }
};

int getCod(int i, int j)
{
    return (i - 1) * n + j;
}

void readFile()
{
    f = fopen("matrice2.in", "r");

    fscanf(f, "%d", &n);
    fscanf(f, "%d", &q);

    int i, j;
    for(i = 1; i <= n; i ++)
    {
        for(j = 1; j <= n; j ++)
        {
            int cod = getCod(i, j);
            lin[cod] = i;

            fscanf(f, "%d", &a[cod]);
        }
    }

    int l, c;
    for(i = 1; i <= q; i ++)
    {
        fscanf(f, "%d%d", &l, &c);
        v[i].x = getCod(l, c);

        fscanf(f, "%d%d", &l, &c);
        v[i].y = getCod(l, c);

        v[i].i = i;
    }

    fclose(f);
}

void init0()
{
    int i, j;
    for(i = 1; i <= n; i ++)
    {
        for(j = 1; j <= n; j ++)
        {
            int cod = getCod(i, j);

            comp[cod] = cod;
            h[cod] = 1;
        }
    }
}

void unestele(int a, int b)
{
   // cout << "UNIM COD " << a << " " << b << "\n";

    if(h[a] >= h[b])
    {
        h[a] += (h[a] == h[b]);

        comp[b] = a;
    }

    else
    {
        comp[a] = b;
    }
}

bool inMat(int l, int c)
{
    return l >= 1 && l <= n && c >= 1 && c <= n;
}

int getComp(int a)
{
    if(comp[a] == a)
        return a;

    return comp[a] = getComp(comp[a]);
}

void uneste(int cod)
{
   // cout << "INTRA\n";
    int i = lin[cod];
    int j = cod - (i - 1) * n;
   // cout << "SUNTEM PE " << cod << " " << i << " " << j << "\n";
    int dir;
    for(dir = 0; dir < MAX_DIR; dir ++)
    {
       // cout << "DIR " << dir << "\n";
        int nl = i + dl[dir];
        int nc = j + dc[dir];
       // cout << "POS " << nl << " " << nc << "\n";
        if(inMat(nl, nc))
        {
            //cout << "E BINE \n";
            int nx = getCod(nl, nc);
            int ca = getComp(cod);
            int cb = getComp(nx);
            if(a[nx] >= a[cod] && ca != cb)
                unestele(ca, cb);
        }
    }
}

int unite(int a, int b)
{
    int ca = getComp(a);
    int cb = getComp(b);

    if(ca == cb)
        return 1;

    return 0;
}

void cautBin()
{
    int nn = n * n;
    int pas = 1 << 20;
    while(pas != 0)
    {
        init0();

        int k = 0;
        for(int i = 1; i <= q; i ++)
            que[++ k] = {v[i].rez + pas, i, 0};

        sort(que + 1, que + q + 1, cmpQ());

        int i = 1;
        int j = 1;
        while(i <= nn && j <= q)
        {
            if(nr[i].x >= que[j].nr)
            {
                uneste(nr[i].cod);
                i ++;
            }

            else
            {
                que[j].ok = unite(v[que[j].i].x, v[que[j].i].y);
                j ++;
            }
        }

        while(j <= q)
        {
            que[j].ok = unite(v[que[j].i].x, v[que[j].i].y);
            j ++;
        }

        for(i = 1; i <= q; i ++)
        {
            if(que[i].ok)
                v[que[i].i].rez = que[i].nr;
        }

        pas >>= 1;
    }
}

void getNr()
{
    int k = 0;
    int i, j;
    for(i = 1; i <= n; i ++)
    {
        for(j = 1; j <= n; j ++)
        {
            int cod = getCod(i, j);
            nr[++ k] = {a[cod], cod};
        }
    }

    sort(nr + 1, nr + n * n + 1, cmpNR());
}

void solve()
{
    getNr();

    cautBin();

    sort(v + 1, v + q + 1, cmpI());
}

void printFile()
{
    g = fopen("matrice2.out", "w");

    int i;
    for(i = 1; i <= q; i ++)
        fprintf(g, "%d\n", v[i].rez);

    fclose(g);
}

int main()
{
    readFile();

    solve();

    printFile();

    return 0;
}