Cod sursa(job #2131749)

Utilizator flaviu_2001Craciun Ioan-Flaviu flaviu_2001 Data 14 februarie 2018 22:08:33
Problema Matrice 2 Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.79 kb
#include <bits/stdc++.h>

using namespace std;

class InParser {
private:
    FILE *fin;
    char *buff;
    int sp;

    char read_ch() {
        ++sp;
        if (sp == 4096) {
            sp = 0;
            fread(buff, 1, 4096, fin);
        }
        return buff[sp];
    }

public:
    InParser(const char* nume) {
        fin = fopen(nume, "r");
        buff = new char[4096]();
        sp = 4095;
    }

    InParser& operator >> (int &n) {
        char c;
        while (!isdigit(c = read_ch()) && c != '-');
        int sgn = 1;
        if (c == '-') {
            n = 0;
            sgn = -1;
        } else {
            n = c - '0';
        }
        while (isdigit(c = read_ch())) {
            n = 10 * n + c - '0';
        }
        n *= sgn;
        return *this;
    }

    InParser& operator >> (long long &n) {
        char c;
        n = 0;
        while (!isdigit(c = read_ch()) && c != '-');
        long long sgn = 1;
        if (c == '-') {
            n = 0;
            sgn = -1;
        } else {
            n = c - '0';
        }
        while (isdigit(c = read_ch())) {
            n = 10 * n + c - '0';
        }
        n *= sgn;
        return *this;
    }
};

class OutParser {
private:
    FILE *fout;
    char *buff;
    int sp;

    void write_ch(char ch) {
        if (sp == 50000) {
            fwrite(buff, 1, 50000, fout);
            sp = 0;
            buff[sp++] = ch;
        } else {
            buff[sp++] = ch;
        }
    }


public:
    OutParser(const char* name) {
        fout = fopen(name, "w");
        buff = new char[50000]();
        sp = 0;
    }
    ~OutParser() {
        fwrite(buff, 1, sp, fout);
        fclose(fout);
    }

    OutParser& operator << (int vu32) {
        if(vu32 == -1){
            write_ch('-');
            write_ch('1');
        } else if (vu32 <= 9) {
            write_ch(vu32 + '0');
        } else {
            (*this) << (vu32 / 10);
            write_ch(vu32 % 10 + '0');
        }
        return *this;
    }

    OutParser& operator << (long long vu64) {
        if (vu64 <= 9) {
            write_ch(vu64 + '0');
        } else {
            (*this) << (vu64 / 10);
            write_ch(vu64 % 10 + '0');
        }
        return *this;
    }

    OutParser& operator << (char ch) {
        write_ch(ch);
        return *this;
    }
    OutParser& operator << (const char *ch) {
        while (*ch) {
            write_ch(*ch);
            ++ch;
        }
        return *this;
    }
};

struct query{
    int x1, y1, x2, y2, i;
    int st, dr, m, ans;
    bool operator<(const query &obj)const{
        return m > obj.m;
    }
};

struct elem{
    int x, y, val;
    bool operator< (const elem &obj)const{
        return val >= obj.val;
    }
};

const int nmax = 305, hmax = 1000005, dx[] = {1, -1, 0, 0}, dy[] = {0, 0, -1, 1};
int n, m, answered, c[nmax*nmax+5], rng[nmax*nmax+5], v[nmax][nmax], sol[20005];
vector<query> q;
vector<elem> e;

query make_query(int x1, int y1, int x2, int y2, int i, int st = 1, int dr = hmax, int m = hmax/2, int ans = 1)
{
    query aux;
    aux.x1 = x1;
    aux.y1 = y1;
    aux.x2 = x2;
    aux.y2 = y2;
    aux.i = i;
    aux.st = st;
    aux.dr = dr;
    aux.m = m;
    aux.ans = ans;
    return aux;
}

elem make_elem(int x, int y, int val)
{
    elem aux;
    aux.x = x;
    aux.y = y;
    aux.val = val;
    return aux;
}

int find(int x)
{
    if(x == c[x])
        return x;
    c[x] = find(c[x]);
    return c[x];
}

void unite(int x, int y)
{
    if(rng[x] > rng[y])
        c[y] = x;
    else c[x] = y;
    if(rng[x] == rng[y])
        ++rng[y];
}

bool check(int x, int y, int val)
{
    return x > 0 && y > 0 && x <= n && y <= n && v[x][y] >= val;
}

int main()
{
    InParser fin ("matrice2.in");
    OutParser fout ("matrice2.out");
    fin >> n >> m;
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= n; ++j){
            int x;
            fin >> x;
            v[i][j] = x;
            e.push_back(make_elem(i, j, x));
        }
    sort(e.begin(), e.end());
    for (int i = 1; i <= m; ++i){
        int x1, y1, x2, y2;
        fin >> x1 >> y1 >> x2 >> y2;
        q.push_back(make_query(x1, y1, x2, y2, i));
    }
    while(answered < m){
        for (int i = 1; i <= nmax*nmax; ++i){
            c[i] = i;
            rng[i] = 1;
        }
        sort(q.begin(), q.end());
        /*for (vector<query>::iterator it = q.begin(); it != q.end(); ++it)
            cout << it->x1 << " " << it->y1 << " " << it->m << "\n";
        cout << "\n";
        return 0;*/
        int p = 0;
        for (vector<elem>::iterator it = e.begin(); it != e.end(); ++it){
            for (int i = 0; i < 4; ++i)
                if(check(it->x+dx[i], it->y+dy[i], v[it->x][it->y]))
                    unite(find(it->x*nmax+it->y), find((it->x+dx[i])*nmax+it->y+dy[i]));
            if(it+1 == e.end() || it->val > (it+1)->val){
                int x = it->val;
                while(q[p].m >= x && p < q.size()){
                    if(q[p].st > q[p].dr){
                        ++p;
                        continue;
                    }
                    if(q[p].x1*nmax+q[p].y1 > nmax*nmax){
                        //cout << "" << "\n";
                        return 0;
                    }
                    if(find(q[p].x1*nmax+q[p].y1) == find(q[p].x2*nmax+q[p].y2)){
                        //if(q[p].i == 1)
                            //cout << x << "\n";
                        q[p].ans = x;
                        q[p].st = q[p].m+1;
                    }else
                        q[p].dr = q[p].m-1;
                    q[p].m = (q[p].st+q[p].dr)/2;
                    if(q[p].st > q[p].dr){
                        ++answered;
                        sol[q[p].i] = q[p].ans;
                    }
                    ++p;
                }
            }
        }
    }
    for (int i = 1; i <= m; ++i)
        fout << sol[i] << "\n";
    return 0;
}