Cod sursa(job #2925303)

Utilizator lolismekAlex Jerpelea lolismek Data 13 octombrie 2022 23:09:04
Problema Matrice 2 Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.72 kb
// TODO: de fixat bug-uri??? (imi este f somn)
#include <algorithm>
#include <iostream>
#include <fstream>
#include <vector>
#include <set>

#define pii pair <int, int>

using namespace std;

ifstream fin("matrice2.in");
ofstream fout("matrice2.out");

const int NMAX = 300, QMAX = 2e4, VMAX = 1e6;

struct Query{
	int x1, y1, x2, y2;
	int st, dr, mij;
	int ans, ind;

	bool operator < (const Query &other) const {
		return ind < other.ind;
	}
};

struct DSU{
	int sz[NMAX + 1][NMAX + 1];
	pii parent[NMAX + 1][NMAX + 1];

	void clear(int n){
		for(int i = 1; i <= n; i++)
			for(int j = 1; j <= n; j++)
				parent[i][j] = {0, 0};
	}

	void init(int n){
		for(int i = 1; i <= n; i++)
			for(int j = 1; j <= n; j++)
				parent[i][j] = {i, j}, sz[i][j] = 1;
	}

	void init(int i, int j){
		parent[i][j] = {i, j};
		sz[i][j] = 1;
	}

	pii Find(int i, int j){
		if(parent[i][j].first == i && parent[i][j].second == j)
			return parent[i][j];
		return parent[i][j] = Find(parent[i][j].first, parent[i][j].second);
	}

	void Union(pii A, pii B){
		pii parentA = Find(A.first, A.second);
		pii parentB = Find(B.first, B.second);

		if((parentA == parentB) || parentA.first == 0 || parentB.first == 0) // TODO: functie de equal
			return;

		if(sz[parentA.first][A.second] < sz[parentB.first][parentB.second])
			swap(parentA, parentB);

		sz[parentA.first][parentA.second] += sz[parentB.first][parentB.second];
		parent[parentB.first][parentB.second] = parentA;
	}

	// N, E, S, V
	int diri[4] = {-1, 0, 1, 0};
	int dirj[4] = {0, 1, 0, -1};

	bool inB(int i, int j, int n){
		return (1 <= i && i <= n && 1 <= j && j <= n);
	}

	void Insert(int i, int j, int n){
		init(i, j);
		for(int dir = 0; dir < 4; dir++){
			int newI = i + diri[dir], newJ = j + dirj[dir];
			if(inB(newI, newJ, n))
				Union({i, j}, {newI, newJ});
		}
	}

	bool Conex(pii A, pii B){
		pii parentA = Find(A.first, A.second);
		pii parentB = Find(B.first, B.second);

		return (parentA == parentB && parentA.first != 0);
	}
};

int n, q, mat[NMAX + 1][NMAX + 1];
vector <pii> pos[VMAX + 1];
vector <int> vals;
set <int> S;
DSU DS; // <3

vector <Query> queries;

void parallelThreadBinarySearch(){
	int K = vals.size();
	while(K > 0){
		K /= 2;

		vector <Query> newQueries, others;
		DS.clear(n);

		int ind = q - 1;
		for(int i = (int)vals.size() - 1; i >= 0; i--){
			for(auto p : pos[vals[i]])
				DS.Insert(p.first, p.second, n);

			others.clear();

			while(ind >= 0 && queries[ind].mij == i){

				if(DS.Conex({queries[ind].x1, queries[ind].y1}, {queries[ind].x2, queries[ind].y2})){
					queries[ind].st = queries[ind].mij + 1,
					queries[ind].mij = (queries[ind].st + queries[ind].dr) / 2;
					queries[ind].ans = vals[i];
					newQueries.push_back(queries[ind]);
				}else{
					queries[ind].dr = queries[ind].mij - 1;
					queries[ind].mij = (queries[ind].st + queries[ind].dr) / 2;
					others.push_back(queries[ind]);
				}

				ind--;
			}

			for(Query query : others)
				newQueries.push_back(query);
		}

		queries = newQueries;
	}
}

int main(){

	fin >> n >> q;

	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= n; j++)
			fin >> mat[i][j], S.insert(mat[i][j]), pos[mat[i][j]].push_back({i, j});

	for(auto it : S)
		vals.push_back(it);
	
	for(int i = 1; i <= q; i++){
		Query query;
		fin >> query.x1 >> query.y1 >> query.x2 >> query.y2, query.ind = i;
		query.st = 0, query.dr = (int)vals.size() - 1;
		query.mij = (query.st + query.dr) / 2;
		queries.push_back(query);
	}

	parallelThreadBinarySearch();

	sort(queries.begin(), queries.end());

	cout << queries.size() << endl;

	for(auto query : queries)
		fout << query.ans << '\n';

	return 0;
}