Cod sursa(job #2272032)

Utilizator andreicoman299Coman Andrei andreicoman299 Data 29 octombrie 2018 17:10:36
Problema Matrice 2 Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.01 kb
#include <bits/stdc++.h>
#define MAXN 300
#define MAXQ 20000

int n, q;
int v[1 + MAXN][1 + MAXN];
struct Query{std::pair <int, int> A, B; int ind, ans;};

std::vector <std::pair <int, int>> V;
bool cmp(std::pair <int, int> A, std::pair <int, int> B){ return v[A.first][A.second] < v[B.first][B.second];}

std::pair <int, int> father[1 + MAXN][1 + MAXN];
int active[1 + MAXN][1 + MAXN];
inline void Union(std::pair <int, int> x, std::pair <int, int> y){
    father[y.first][y.second] = x;
}
inline std::pair <int, int> Find(std::pair <int, int> x){
    if(father[x.first][x.second] == std::make_pair(0, 0))
        return x;
    std::pair <int, int> y = Find(father[x.first][x.second]);
    father[x.first][x.second] = y;
    return y;
}

int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
inline void add(std::pair <int, int> x){
    active[x.first][x.second] = 1;
    for(int k = 0; k < 4; k++){
        int l = x.first + dir[k][0], c = x.second + dir[k][1];
        if(1 <= l && l <= n && 1 <= c && c <= n && active[l][c])
            if(Find(x) != Find({l, c}))
                Union(Find(x), Find({l, c}));
    }
}

std::vector <Query> Q, S, T;
int ans[1 + MAXQ];

int main(){
    FILE*fi,*fo;
    fi = fopen("matrice2.in","r");
    fo = fopen("matrice2.out","w");

    fscanf(fi,"%d%d", &n, &q);
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++){
            fscanf(fi,"%d", &v[i][j]);
            V.push_back({i, j});
        }
    std::sort(V.begin(), V.end(), cmp);

    for(int i = 1; i <= q; i++){
        Query tmp;
        fscanf(fi,"%d%d%d%d", &tmp.A.first, &tmp.A.second, &tmp.B.first, &tmp.B.second);
        tmp.ind = i;
        tmp.ans = 0;
        Q.push_back(tmp);
    }

    for(int p = (1 << 19); p; p /= 2){
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                active[i][j] = 0, father[i][j] = {0, 0};
        int next = V.size() - 1;
        while(!Q.empty()){
            while(next >= 0 && v[V[next].first][V[next].second] >= Q.back().ans + p)
                add(V[next]), next--;
            if(!active[Q.back().A.first][Q.back().A.second] ||
               !active[Q.back().B.first][Q.back().B.second] ||
               Find(Q.back().A) != Find(Q.back().B))
                T.push_back(Q.back());
            else
                Q.back().ans += p, S.push_back(Q.back());
            Q.pop_back();
        }
        std::reverse(S.begin(), S.end());
        std::reverse(T.begin(), T.end());
        while(!S.empty() && !T.empty()){
            if(S.back().ans > T.back().ans)
                Q.push_back(S.back()), S.pop_back();
            else
                Q.push_back(T.back()), T.pop_back();
        }
        while(!S.empty()) Q.push_back(S.back()), S.pop_back();
        while(!T.empty()) Q.push_back(T.back()), T.pop_back();
        std::reverse(Q.begin(), Q.end());
    }

    for(auto y: Q) ans[y.ind] = y.ans;
    for(int i = 1; i <= q; i++)
        fprintf(fo,"%d\n", ans[i]);

    return 0;
}