Cod sursa(job #665227)

Utilizator skipyGiurgea Mihnea skipy Data 21 ianuarie 2012 20:07:11
Problema Matrice 2 Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.52 kb
#include <cstdio>
#include <cassert>

#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <utility>
using namespace std;

#define FORIT(it, v) for (typeof((v).begin()) it = (v).begin(); it != (v).end(); ++it)

const int MAXN = 303;
const int MAXQ = 20013;
const int dx[4] = { -1, 0, 1, 0 };
const int dy[4] = { 0, 1, 0, -1 };

struct query {
    int x1, y1, x2, y2;
};

int A[MAXN][MAXN], N, Q;
query queries[MAXQ];
int sol[MAXQ];
vector< pair<int, int> > B;
multimap<int, int> mm;

inline bool inside(int x, int y) {
    return (1 <= x && x <= N && 1 <= y && y <= N);
}

// Disjoint sets
int pi[MAXN*MAXN], rank[MAXN*MAXN];
int member[MAXN][MAXN], nr_members;

inline void make_set(int x) {
    pi[x] = x;
    rank[x] = 0;
}

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

void merge(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (rank[x] < rank[y])
        pi[x] = y;
    else if (rank[x] > rank[y])
        pi[y] = x;
    else {
        pi[x] = y;
        rank[y]++;
    }
}

void read() {
    assert( scanf("%d %d", &N, &Q) == 2 );
    for (int i = 1; i <= N; i++)
        for (int j = 1; j <= N; j++)
            assert( scanf("%d", &A[i][j]) == 1);
    for (int i = 0; i < Q; i++) {
        query q;
        assert( scanf("%d %d %d %d", &q.x1, &q.y1, &q.x2, &q.y2) == 4 );
        queries[i] = q;
    }
}

bool cmp(pair<int, int> i, pair<int, int> j) {
    return (A[i.first][i.second] > A[j.first][j.second]);
}

inline bool issatisfied(query q) {
    int a, b;
    a = member[q.x1][q.y1];
    b = member[q.x2][q.y2];
    if (!a || !b) return false;
    return ( find(a) == find(b) );
}

void step(int delta) {
    nr_members = 1;
    for (int i = 1; i <= N; i++)
        for (int j = 1; j <= N; j++)
            member[i][j] = 0;
    // Sort queries by their sol.
    for (int i = 0; i < Q; i++)
        mm.insert( make_pair(sol[i] + delta, i) );

    multimap<int,int>::iterator mmit = mm.begin();

    int x, y, nx, ny, k;
    for (int i = 0; i < (int)B.size();) {
        x = B[i].first;
        y = B[i].second;

        member[x][y] = nr_members;
        make_set(nr_members);
        nr_members++;

        for (k = 0; k < 4; k++) {
            nx = x + dx[k];
            ny = y + dy[k];
            if ( inside(nx, ny) && member[nx][ny] != 0 ) {
                merge( member[x][y], member[nx][ny] );
            }
        }
        ++i;
        for (; mmit != mm.end() && mmit->first == i; ++mmit) {
            //printf("Checking query #%d (val=%d | %d) when i = %d\n",
            //       mmit->second, mmit->first, A[x][y], i);
            if ( !issatisfied(queries[mmit->second]) )
                sol[mmit->second] += delta;
        }
    }

    mm.clear();

    //printf("   Sol (delta=%3d): ", delta);
    //for (int i = 0; i < Q; i++) printf("%2d ", sol[i]);
    //printf("\n");
}

void solve() {
    for (int i = 1; i <= N; i++)
        for (int j = 1; j <= N; j++)
            B.push_back(make_pair(i, j));
    sort(B.begin(), B.end(), cmp);

    //for (int i = 0; i < (int)B.size(); ++i)
    //    printf("B#%2d: %d\n", i, A[B[i].first][B[i].second]);

    int delta;
    for (delta = 1; delta < (int)B.size(); delta <<= 1);
    for (; delta; delta >>= 1)
        step(delta);

    pair<int, int> p;
    for (int i = 0; i < Q; i++) {
        p = B[sol[i]];
        printf("%d\n", A[p.first][p.second] );
    }
}

int main() {
    assert( freopen("matrice2.in", "r", stdin) );
    assert( freopen("matrice2.out", "w", stdout) );

    read();
    solve();

    return 0;
}