Submission #105391

#TimeUsernameProblemLanguageResultExecution timeMemory
105391Noam527Golf (JOI17_golf)C++17
100 / 100
4481 ms329148 KiB
#include <bits/stdc++.h>
#define CHECK cout << "ok" << endl
#define finish(x) return cout << x << endl, 0
typedef long long ll;
typedef long double ldb;
const int md = 1e9 + 7;
const ll inf = 1e18;
const int OO = 0;
const int OOO = 1;
using namespace std;

struct rect {
	int t, b, l, r;
	rect() {}
	rect(int tt, int bb, int ll, int rr) : t(tt), b(bb), l(ll), r(rr) {}
};
// v(0) = insert, v(1) = delete, v(2) = query
struct eve {
	int v, t, l, r;
	eve() {}
	eve(int vv, int tt, int ll, int rr) : v(vv), t(tt), l(ll), r(rr) {}
	bool operator < (const eve &a) const {
		if (t != a.t) return t < a.t;
		return v < a.v;
	}
};
struct line {
	int d, l, r, i;
	line() {}
	line(int dd, int ll, int rr, int ii = 0) : d(dd), l(ll), r(rr), i(ii) {}
	bool operator < (const line &a) const {
		if (d != a.d) return d < a.d;
		if (l != a.l) return l < a.l;
		return r < a.r;
	}
	bool operator == (const line &a) const {
		return d == a.d && l == a.l && r == a.r;
	}
};
struct segtree {
	int n;
	vector<set<line>> t;
	segtree() {}
	segtree(int sz) {
		n = max(2, sz);
		while (n != (n & -n)) n += (n & -n);
		t.resize(2 * n);
	}
	void add(const line &a) {
		add(a, 0, 0, 0, n - 1);
	}
	void erase(const line &a) {
		add(a, 1, 0, 0, n - 1);
	}
	void add(const line &a, int type, int node, int nl, int nr) {
		if (a.r < nl || nr < a.l) return;
		if (a.l <= nl && nr <= a.r) {
			if (type == 0) t[node].insert(a);
			else t[node].erase(a);
			return;
		}
		int mid = (nl + nr) / 2;
		add(a, type, 2 * node + 1, nl, mid);
		add(a, type, 2 * node + 2, mid + 1, nr);
	}
	line getrid(const line &a) {
		erase(a);
		return a;
	}
	line query(const line &a) {
		int pos = a.d + n - 1;
		set<line>::iterator it;
		line S(a.l, 0, 0, 0);
		if (OO) {
			cout << "find cut of " << a.d << " " << a.l << " " << a.r << '\n';
			cout << "in:\n";
			for (const auto &i : t[pos]) cout << i.d << " " << i.l << " " << i.r << '\n';
		}
		it = t[pos].lower_bound(S);
		if (it != t[pos].end() && it->d <= a.r) return getrid(*it);
		pos = (pos - 1) / 2;
		while (pos) {
			if (OO) {
				cout << "find cut of " << a.d << " " << a.l << " " << a.r << '\n';
				cout << "in:\n";
				for (const auto &i : t[pos]) cout << i.d << " " << i.l << " " << i.r << '\n';
			}
			it = t[pos].lower_bound(S);
			if (it != t[pos].end() && it->d <= a.r) return getrid(*it);
			pos = (pos - 1) / 2;
		}
		if (OO) {
			cout << "find cut of " << a.d << " " << a.l << " " << a.r << '\n';
			cout << "in:\n";
			for (const auto &i : t[pos]) cout << i.d << " " << i.l << " " << i.r << '\n';
		}
		it = t[pos].lower_bound(S);
		if (it != t[pos].end() && it->d <= a.r) return getrid(*it);
		return line(-1, -1, -1, -1);
	}
};

pair<int, int> st, en;
int n, MX, MY;
vector<rect> r;
vector<line> V, H;
segtree TV, TH;

vector<int> dv, dh;

void compress() {
	vector<int> compx, compy;
	compx.reserve(2 * n + 2);
	compy.reserve(2 * n + 2);
	compx.push_back(st.first), compx.push_back(en.first);
	compy.push_back(st.second), compy.push_back(en.second);
	for (auto &i : r) {
		compx.push_back(i.l), compx.push_back(i.r);
		compy.push_back(i.b), compy.push_back(i.t);
	}
	sort(compx.begin(), compx.end());
	sort(compy.begin(), compy.end());
	compx.resize(unique(compx.begin(), compx.end()) - compx.begin());
	compy.resize(unique(compy.begin(), compy.end()) - compy.begin());
	auto MP = [](const vector<int> &aa, int &value) {
		value = lower_bound(aa.begin(), aa.end(), value) - aa.begin();
	};
	MP(compx, st.first), MP(compx, en.first);
	MP(compy, st.second), MP(compy, en.second);
	for (auto &i : r) {
		MP(compx, i.l), MP(compx, i.r);
		MP(compy, i.b), MP(compy, i.t);
	}
	MX = compx.size();
	MY = compy.size();
}

void calc_vertical() {
	vector<eve> E;
	E.reserve(4 * n + 2);
	E.push_back(eve(2, st.first, st.second, st.second));
	E.push_back(eve(2, en.first, en.second, en.second));
	for (auto &i : r) {
		E.push_back(eve(0, i.l + 1, i.b, i.t));
		E.push_back(eve(2, i.l, i.b, i.b));
		E.push_back(eve(1, i.r, i.b, i.t));
		E.push_back(eve(2, i.r, i.b, i.b));
	}
	sort(E.begin(), E.end());
	set<pair<int, int>> bl;
	for (const auto &i : E) {
		if (i.v == 0)
			bl.insert({ i.l, i.r });
		else if (i.v == 1)
			bl.erase({ i.l, i.r });
		else {
			int lo, hi;
			auto it = bl.lower_bound({ i.l,i.l });
			if (it == bl.end()) hi = MY - 1;
			else hi = it->first;
			if (it == bl.begin()) lo = 0;
			else {
				it--;
				lo = it->second;
			}
			V.push_back(line(i.t, lo, hi));
		}
	}
	V.push_back(line(0, 0, MY - 1));
	V.push_back(line(MX - 1, 0, MY - 1));
	sort(V.begin(), V.end());
	V.resize(unique(V.begin(), V.end()) - V.begin());
	for (int i = 0; i < V.size(); i++) V[i].i = i;
}

void calc_horizontal() {
	vector<eve> E;
	E.reserve(3 * n + 2);
	E.push_back(eve(2, st.second, st.first, st.first));
	E.push_back(eve(2, en.second, en.first, en.first));
	for (auto &i : r) {
		E.push_back(eve(0, i.b + 1, i.l, i.r));
		E.push_back(eve(2, i.b, i.l, i.l));
		E.push_back(eve(1, i.t, i.l, i.r));
		E.push_back(eve(2, i.t, i.l, i.l));
	}
	sort(E.begin(), E.end());
	set<pair<int, int>> bl;
	for (const auto &i : E) {
		if (i.v == 0)
			bl.insert({ i.l, i.r });
		else if (i.v == 1)
			bl.erase({ i.l, i.r });
		else {
			int lo, hi;
			auto it = bl.lower_bound({ i.l,i.l });
			if (it == bl.end()) hi = MX - 1;
			else hi = it->first;
			if (it == bl.begin()) lo = 0;
			else {
				it--;
				lo = it->second;
			}
			H.push_back(line(i.t, lo, hi));
		}
	}
	H.push_back(line(0, 0, MX - 1));
	H.push_back(line(MY - 1, 0, MX - 1));
	sort(H.begin(), H.end());
	H.resize(unique(H.begin(), H.end()) - H.begin());
	for (int i = 0; i < H.size(); i++) H[i].i = i;
}

void bfs(int startv, int starth) {
	dv.resize(V.size(), -1);
	dh.resize(H.size(), -1);
	dv[startv] = dh[starth] = 0;
	TV.erase(V[startv]);
	TH.erase(H[starth]);
	queue<pair<int, int>> q;
	q.push({ startv, 0 });
	q.push({ starth, 1 });
	while (q.size()) {
		pair<int, int> x = q.front();
		q.pop();
		if (OO) {
			cout << "bfs on " << x.first << " " << x.second << '\n';
			cout << "with distance ";
			if (x.second == 0) cout << dv[x.first] << '\n';
			else cout << dh[x.first] << '\n';
		}
		if (x.second == 0) {
			// current is vertical
			line c = TH.query(V[x.first]);
			while (c.d != -1) {
				dh[c.i] = 1 + dv[x.first];
				q.push({ c.i, 1 });
				c = TH.query(V[x.first]);
			}
		}
		else {
			line c = TV.query(H[x.first]);
			while (c.d != -1) {
				dv[c.i] = 1 + dh[x.first];
				q.push({ c.i, 0 });
				c = TV.query(H[x.first]);
			}
		}
	}
}

int main() {
	ios::sync_with_stdio(0), cin.tie(0);
	cin >> st.first >> st.second >> en.first >> en.second;
	cin >> n;
	r.resize(n);
	for (auto &i : r) cin >> i.l >> i.r >> i.b >> i.t;
	compress();
	calc_vertical();
	calc_horizontal();
	if (OO) {
		cout << "start " << st.first << " " << st.second << '\n';
		cout << "end " << en.first << " " << en.second << '\n';
		cout << "rectangles\n";
		for (const auto &i : r) {
			cout << i.l << " " << i.b << " " << i.r << " " << i.t << '\n';
		}
		cout << "verticals\n";
		for (const auto &i : V) cout << i.d << ", [" << i.l << " " << i.r << "]\n";
		cout << "horizontals\n";
		for (const auto &i : H) cout << i.d << ", [" << i.l << " " << i.r << "]\n";
	}

	TV = segtree(MY);
	TH = segtree(MX);
	for (const auto &i : V) TV.add(i);
	for (const auto &i : H) TH.add(i);
	int starth, startv, endh, endv;
	for (const auto &i : V) {
		if (i.d == st.first && i.l <= st.second && st.second <= i.r) startv = i.i;
		if (i.d == en.first && i.l <= en.second && en.second <= i.r) endv = i.i;
	}
	for (const auto &i : H) {
		if (i.d == st.second && i.l <= st.first && st.first <= i.r) starth = i.i;
		if (i.d == en.second && i.l <= en.first && en.first <= i.r) endh = i.i;
	}
	bfs(startv, starth);
	cout << 1 + min(dv[endv], dh[endh]) << '\n';
}

Compilation message (stderr)

golf.cpp: In function 'void calc_vertical()':
golf.cpp:173:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < V.size(); i++) V[i].i = i;
                  ~~^~~~~~~~~~
golf.cpp: In function 'void calc_horizontal()':
golf.cpp:211:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for (int i = 0; i < H.size(); i++) H[i].i = i;
                  ~~^~~~~~~~~~
golf.cpp: In function 'int main()':
golf.cpp:288:25: warning: 'endv' may be used uninitialized in this function [-Wmaybe-uninitialized]
  cout << 1 + min(dv[endv], dh[endh]) << '\n';
                         ^
golf.cpp:287:5: warning: 'startv' may be used uninitialized in this function [-Wmaybe-uninitialized]
  bfs(startv, starth);
  ~~~^~~~~~~~~~~~~~~~
golf.cpp:288:35: warning: 'endh' may be used uninitialized in this function [-Wmaybe-uninitialized]
  cout << 1 + min(dv[endv], dh[endh]) << '\n';
                                   ^
golf.cpp:287:5: warning: 'starth' may be used uninitialized in this function [-Wmaybe-uninitialized]
  bfs(startv, starth);
  ~~~^~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...