Submission #1359825

#TimeUsernameProblemLanguageResultExecution timeMemory
1359825vlomaczkBitaro's Travel 2 (JOI25_travel2)C++20
0 / 100
670 ms76228 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
using namespace __gnu_pbds;
using namespace std;

template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

struct Query {
	ll a, b, c, d, f, s;
};

struct DSU {
	vector<ll> rep, sajz;
	vector<pair<ll, ll>> mx;
	
	DSU(ll n) {
		rep.resize(n+1);
		sajz.assign(n+1,1);
		mx.assign(n+1, {});
		for(ll i=0; i<=n; ++i) rep[i] = i;
	}

	void ustaw(ll x, ll val) {
		mx[x] = {val, x};
	}

	ll Find(ll v) {
		return rep[v] == v ? v : rep[v] = Find(rep[v]);
	}

	bool Union(ll a, ll b) {
		a=Find(a);
		b=Find(b);
		if(a==b) return 0;
		if(sajz[b] > sajz[a]) swap(a,b);
		rep[b] = a;
		sajz[a] += sajz[b];
		mx[a] = max(mx[a], mx[b]);
		return 1;
	}
};

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);

	ll h,w,L;
	cin >> h >> w >> L;
	vector<vector<ll>> T(h, vector<ll>(w));
	for(ll i=0; i<h; ++i) {
		for(ll j=0; j<w; ++j) cin >> T[i][j];
	}

	auto trans = [&](ll a, ll b) { return a*w + b; };
	auto tb = [&](ll x) { return make_pair(x/w, x%w); };

	ll q; cin >> q;
	vector<Query> zap(q);
	for(ll i=0; i<q; ++i) {
		cin >> zap[i].a >> zap[i].b >> zap[i].c >> zap[i].d;
		zap[i].a--; zap[i].b--; zap[i].c--; zap[i].d--;
		zap[i].f = trans(zap[i].a, zap[i].b);
		zap[i].s = trans(zap[i].c, zap[i].d);
	}

	ll n = w*h + 10;
	DSU mst(n), dsu(n), tree(n);
	map<ll, vector<ll>> mapa;
	for(ll i=0; i<h; ++i) {
		for(ll j=0; j<w; ++j) {
			mapa[T[i][j]].push_back(trans(i,j));
		}
	}
	auto proba = [&](ll x, ll a, ll b, DSU &D) {
		auto[c,d] = tb(x);
		if(a < 0 || a >= h || b < 0 || b >= w || T[a][b] > T[c][d]) return;
		D.Union(x, trans(a,b));
	};
	auto connect = [&](ll x, DSU &D) {
		auto[a,b] = tb(x);
		proba(x, a+1, b, D);
		proba(x, a-1, b, D);
		proba(x, a, b+1, D);
		proba(x, a, b-1, D);
	};
	
	for(auto[t, vec] : mapa) {
		for(auto x : vec) connect(x, mst);
		map<ll, ll> prio;
		for(auto x : vec) {
			if(prio.find(mst.Find(x)) == prio.end()) prio[mst.Find(x)] = x;
			else dsu.Union(x, prio[mst.Find(x)]);
		}
	}
	vector<ll> edge(n);
	vector<ll> heights;
	for(ll i=0; i<h; ++i) for(ll j=0; j<w; ++j) heights.push_back(T[i][j]);
	sort(heights.begin(), heights.end());
	map<ll, vector<ll>> check;
	DSU mxdsu(n);
	for(ll i=0; i<h; ++i) for(ll j=0; j<w; ++j) {
		mxdsu.ustaw(trans(i,j), T[i][j]);
		auto it = upper_bound(heights.begin(), heights.end(), T[i][j] + L);
		if(it==heights.end()) edge[trans(i,j)] = dsu.Find(mapa.rbegin()->second[0]);
		else check[*it].push_back(trans(i,j));
	}	
	for(auto[t, vec] : mapa) {
		for(auto x : check[t]) edge[x] = mxdsu.mx[mxdsu.Find(x)].second;
		for(auto x : vec) connect(x, mxdsu);
	}
	for(auto &x : edge) x = dsu.Find(x);
	for(ll i=0; i<h; ++i) for(ll j=0; j<w; ++j) {
		// auto[a,b] = tb(dsu.Find(trans(i,j)));
		// cout << "(" << i << " " << j << "): " << a << " " << b << "\n";

		// auto[c,d] = tb(edge[trans(i,j)]);
		// cout << "(" << i << " " << j << "): " << c << " " << d << "\n";
	}	
	;vector<ll> depth(n);
	for(auto it=mapa.rbegin(); it!=mapa.rend(); ++it) {
		for(auto x : it->second) {
			if(dsu.Find(x) != x) continue;
			tree.Union(x, edge[x]);
			depth[x] = depth[edge[x]] + 1;
		}
	}
	vector<ll> lo(q,0), hi(q, (ll)mapa.size() - 1), mid(q);
	while(1) {
		ll ile = 0;
		vector<vector<ll>> sweep(mapa.size());
		for(ll x=0; x<q; ++x) {
			if(lo[x] < hi[x]) {
				ile++;
				mid[x] = (lo[x] + hi[x]) / 2;
				sweep[mid[x]].push_back(x);
			}
		}
		if(!ile) break;
		DSU dsu2(n);
		for(ll i=0; i<h; ++i) for(ll j=0; j<w; ++j) dsu2.ustaw(trans(i,j), T[i][j]);
		ll idx = 0;
		for(auto[t, vec] : mapa) {
			for(auto x : vec) connect(x, dsu2);
			for(auto x : sweep[idx]) {
				if(dsu2.Find(zap[x].f) == dsu2.Find(zap[x].s)) hi[x] = mid[x];
				else lo[x] = mid[x] + 1;
			}
			idx++;
		}
	}
	vector<vector<ll>> sweep(mapa.size());
	vector<ll> target(q);
	for(ll x=0; x<q; ++x) sweep[lo[x]].push_back(x);
	DSU dsu2(n);
	for(ll i=0; i<h; ++i) for(ll j=0; j<w; ++j) dsu2.ustaw(trans(i,j), T[i][j]);
	ll idx = 0;
	for(auto[t, vec] : mapa) {
		for(auto x : vec) connect(x, dsu2);
		for(auto i : sweep[idx]) target[i] = dsu.Find(dsu2.mx[dsu2.Find(zap[i].f)].second);
		idx++;
	}
	for(ll i=0; i<q; ++i) {
		zap[i].f = dsu.Find(zap[i].f);
		if(tree.Find(zap[i].f) != tree.Find(target[i])) cout << "-1\n";
		else cout << max(0LL, depth[zap[i].f] - depth[target[i]]) << "\n";
	}

	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...