Cod sursa(job #1207839)

Utilizator PlayLikeNeverB4George Marcus PlayLikeNeverB4 Data 14 iulie 2014 02:14:21
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.54 kb
#include <cstdio>
#include <iostream>
#include <fstream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <sstream>
#include <iomanip>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <string>
#include <ctime>
#include <cassert>
#include <utility>

using namespace std;

#define MAXN 305
#define MAXQ 20050

struct Query {
    int idx1, idx2;
    int st, dr;
    int ans;
    int qid;
    
    Query(int idx1, int idx2, int n, int qid) : idx1(idx1), idx2(idx2), qid(qid) {
        st = 0;
        dr = n * n - 1;
        ans = -1;
    }
    
    int mid() {
        return (st + dr) / 2;
    }
};

int N, Q;
int A[MAXN][MAXN];
pair<int, pair<int, int> > B[MAXN * MAXN];
int X1, Y1, X2, Y2;
vector<Query> qs;
int T[MAXN * MAXN];
int ans[MAXQ];

const int di[] = { 1, 0, -1, 0 };
const int dj[] = { 0, 1, 0, -1 };

bool comp(const Query &a, const Query &b) {
    int ma = (a.st + a.dr) / 2;
    int mb = (b.st + b.dr) / 2;
    return ma < mb;
}

int root(int t) {
    if (T[t] != t) {
        T[t] = root(T[t]);
    }
    return T[t];
}

void unite(int ra, int rb) {
    if (ra == rb) {
        return;
    }
    
    if (rand() & 1) {
        T[ra] = rb;
    }
    else {
        T[rb] = ra;
    }
}

int main() {
	freopen("matrice2.in", "r", stdin);
	freopen("matrice2.out","w", stdout);
	
	srand(time(NULL));
	
	scanf("%d %d", &N, &Q);
	for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            scanf("%d", &A[i][j]);
            B[i * N + j] = make_pair(A[i][j], make_pair(i, j));
        }
	}
	sort(B, B + N * N);
	for (int i = 0; i < Q; i++) {
        scanf("%d %d %d %d", &X1, &Y1, &X2, &Y2);
        X1--; Y1--; X2--; Y2--;
        qs.push_back(Query(X1 * N + Y1, X2 * N + Y2, N, i));
	}
	
	bool ok = true;
	while (ok) {
        ok = false;
        
        sort(qs.begin(), qs.end(), comp);
        for (int i = 0; i < N * N; i++) {
            T[i] = i;
        }
        
        int j = Q - 1;
        for (int i = N * N - 1; i >= 0; i--) {
            int pi = B[i].second.first;
            int pj = B[i].second.second;
            int idx = pi * N + pj;
            
            for (int d = 0; d < 4; d++) {
                int ni = pi + di[d];
                int nj = pj + dj[d];
                if (ni >= 0 && ni < N && nj >= 0 && nj < N && A[pi][pj] <= A[ni][nj]) {
                    int nidx = ni * N + nj;
                    unite(root(idx), root(nidx));
                }
            }
            
            while (j >= 0 && qs[j].mid() == i) {
                if (qs[j].st > qs[j].dr) {
                    j--;
                    continue;
                }
                ok = true;
                
                int a = qs[j].idx1;
                int b = qs[j].idx2;
                int m = qs[j].mid();
                if (root(a) == root(b)) {
                    qs[j].ans = m;
                    qs[j].st = m + 1;
                }
                else {
                    qs[j].dr = m - 1;
                }
                
                j--;
            }
        }
	}
	
	for (int i = 0; i < Q; i++) {
	    int crt = B[qs[i].ans].first;
	    crt = min(crt, A[qs[i].idx1 / N][qs[i].idx1 % N]);
	    crt = min(crt, A[qs[i].idx2 / N][qs[i].idx2 % N]);
        ans[qs[i].qid] = crt;
	}
	
	for (int i = 0; i < Q; i++) {
        printf("%d\n", ans[i]);
	}
	
	return 0;
}