Submission #544894

#TimeUsernameProblemLanguageResultExecution timeMemory
544894skittles1412Worm Worries (BOI18_worm)C++17
22 / 100
732 ms500344 KiB
#include "bits/extc++.h"

using namespace std;

template <typename T>
void dbgh(const T& t) {
	cerr << t << endl;
}

template <typename T, typename... U>
void dbgh(const T& t, const U&... u) {
	cerr << t << " | ";
	dbgh(u...);
}

#ifdef DEBUG
#define dbg(...)                                           \
	cerr << "L" << __LINE__ << " [" << #__VA_ARGS__ << "]" \
		 << ": ";                                          \
	dbgh(__VA_ARGS__)
#else
#define cerr   \
	if (false) \
	cerr
#define dbg(...)
#endif

#define endl "\n"
#define long int64_t
#define sz(x) int((x).size())

mt19937 cowng(chrono::steady_clock::now().time_since_epoch().count());

int rint(int n) {
	return int(cowng() % n);
}

int rint(int l, int r) {
	return rint(r - l + 1) + l;
}

namespace d3 {
const int dx[] = {0, 0, 0, 0, -1, 1}, dy[] = {0, 0, -1, 1, 0, 0}, dz[] = {-1, 1, 0, 0, 0, 0};
}

namespace wrapper {

using namespace d3;

int n, m, k, q, queries;
vector<vector<vector<int>>> arrv, cache;

#ifdef GEN
void genrand() {
	for (auto& a : arrv) {
		for (auto& b : a) {
			for (auto& c : b) {
				c = cowng() % int(1e9);
			}
		}
	}
}
#endif

bool ibs(int x, int y, int z) {
	return 0 <= x && x < n && 0 <= y && y < m && 0 <= z && z < k;
}

void init(int _n, int _m, int _k, int _q) {
	tie(n, m, k, q) = tie(_n, _m, _k, _q);
	queries = 0;
	cache.resize(n, vector<vector<int>>(m, vector<int>(k, -1)));
#ifdef GEN
	arrv = cache;
	genrand();
#endif
}

int query(int x, int y, int z) {
	int& ans = cache[x][y][z];
	if (ans != -1) {
		return ans;
	}
	queries++;
	assert(queries <= q);
#ifndef GEN
	cout << "? " << x + 1 << " " << y + 1 << " " << z + 1 << endl;
	cin >> ans;
#else
	ans = arrv[x][y][z];
#endif
	return ans;
};

int answer(int x, int y, int z) {
#ifdef GEN
	cout << "queries: " << queries << endl;
	for (int i = 0; i < 6; i++) {
		int cx = x + dx[i], cy = y + dy[i], cz = z + dz[i];
		if (ibs(cx, cy, cz)) {
			assert(arrv[x][y][z] >= arrv[cx][cy][cz]);
		}
	}
#endif
	cout << "! " << x + 1 << " " << y + 1 << " " << z + 1 << endl;
	exit(0);
};

}  // namespace wrapper

using wrapper::query, wrapper::answer, wrapper::ibs;

namespace s1 {

bool solve(int n, int m, int k, int q) {
#ifdef GEN
	int ogrid[n];
	for (auto& a : ogrid) {
		a = rint(int(1e9));
	}
#endif
	if (m != 1 || k != 1) {
		return false;
	}
	int cache[n];
	memset(cache, -1, sizeof(cache));
	auto queryuc = [&](int i) -> int {
#ifndef GEN
		cout << "? " << i + 1 << " 1 1" << endl;
		int x;
		cin >> x;
		return x;
#else
		return ogrid[i];
#endif
	};
	auto query = [&](int i) -> int {
		if (!(0 <= i && i < n)) {
			return -1e9;
		}
		if (cache[i] != -1) {
			return cache[i];
		}
		static int qcnt = 0;
		qcnt++;
		assert(qcnt <= q);
		return cache[i] = queryuc(i);
	};
	auto answer = [&](int i) -> void {
		cout << "! " << i + 1 << " 1 1" << endl;
		exit(0);
	};
	auto check = [&](int i) -> void {
		if (query(i) >= max(query(i - 1), query(i + 1))) {
			dbg(query(i), query(i - 1), query(i + 1));
			answer(i);
		}
	};
	int l = 0, r = n - 1;
	while ((r - l + 1) > 3) {
		int madd = (r - l + 1) / 3, m1 = l + madd, m2 = r - madd;
		dbg(l, r, m1, m2);
		int a = query(m1), b = query(m2);
		if (a < b) {
			l = m1;
		} else if (a == b) {
			l = m1;
			r = m2;
		} else if (a > b) {
			r = m2;
		}
	}
	if (l == r) {
		answer(l);
	} else if (l + 1 == r) {
		check(l);
		answer(r);
	} else {
		check(l + 1);
		check(l);
		answer(r);
	}
	return true;
}

}  // namespace s1

//#define GEN

namespace s2 {

using namespace d3;

bool solve(int n, int m, int l, int q) {
	pair<int, array<int, 3>> opt {-1, {0, 0, 0}};
	int iter = 500;
	if (q == 3500) {
		iter = 900;
	}
	auto upd = [&](int x, int y, int z) -> void {
		opt = max(opt, pair<int, array<int, 3>> {query(x, y, z), {x, y, z}});
	};
	for (int i = 0; i < iter; i++) {
		int x = rint(n), y = rint(m), z = rint(l);
		upd(x, y, z);
	}
	auto [x, y, z] = opt.second;
	int cnt[6] {};
	deque<int> last;
	while (true) {
		int ord[6];
		iota(begin(ord), end(ord), 0);
		sort(begin(ord), end(ord), [&](int a, int b) -> bool {
			return cnt[a] > cnt[b];
		});
		for (auto& k : ord) {
			int cx = x + dx[k], cy = y + dy[k], cz = z + dz[k];
			if (ibs(cx, cy, cz)) {
				if (query(cx, cy, cz) > query(x, y, z)) {
					cnt[k]++;
					last.push_front(k);
					if (sz(last) == 5) {
						cnt[last.back()]--;
						last.pop_back();
					}
					tie(x, y, z) = tie(cx, cy, cz);
					goto loop;
				}
			}
		}
		answer(x, y, z);
		return true;
	loop:;
	}
}

}  // namespace s2

namespace s3 {

using namespace d3;

bool solve(int n, int m, int l, int q) {
	if (q < int(1e5)) {
		return false;
	}
	array<int, 4> opt {};
	for (int i = 0; i < q / 2; i++) {
		int x = rint(n), y = rint(m), z = rint(l);
		opt = max(opt, {query(x, y, z), x, y, z});
	}
	auto [x, y, z, _] = opt;
	while (true) {
		for (int k = 0; k < 6; k++) {
			int cx = x + dx[k], cy = y + dy[k], cz = z + dz[k];
			if (ibs(cx, cy, cz) && query(cx, cy, cz) > query(x, y, z)) {
				tie(x, y, z) = tie(cx, cy, cz);
				goto loop;
			}
		}
		answer(x, y, z);
		return true;
	loop:;
	}
}

}  // namespace s3

void solve() {
	int n, m, k, q;
	cin >> n >> m >> k >> q;
	wrapper::init(n, m, k, q);
	s1::solve(n, m, k, q) || s3::solve(n, m, k, q) || s2::solve(n, m, k, q);
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.exceptions(ios::failbit);
	solve();
}
#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...