Submission #923436

#TimeUsernameProblemLanguageResultExecution timeMemory
923436Gromp15The Kingdom of JOIOI (JOI17_joioi)C++17
100 / 100
808 ms55124 KiB
#include <bits/stdc++.h>
#define ll long long
#define ar array
#define db double
#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define rint(l, r) uniform_int_distribution<int>(l, r)(rng)
template<typename T> bool ckmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }
template<typename T> bool ckmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }
const int INF = 1e9;
void test_case() {
	int n, m;
	cin >> n >> m;
	vector<vector<int>> a(n+1, vector<int>(m+1));
	int mx = 0, mn = INF;
	for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) { 
		cin >> a[i][j];
		ckmax(mx, a[i][j]);
		ckmin(mn, a[i][j]);
	}
	vector<ar<int, 3>> vals(8);
	for (int i = 0; i < 8; i++) {
		vals[i][0] = i >> 2 & 1;
		vals[i][1] = i >> 1 & 1;
		vals[i][2] = i & 1;
	}
	int ans = mx - mn;
	// give the max/min to who
	for (int A = 0; A < 2; A++) {
		// !A = left has max, right has min
		// A = left has min, right has max
		vector<vector<int>> dp(8, vector<int>(m+1, INF));
		auto conv = [](int vis_left, int vis_right, int order) {
			return (vis_left << 2) + (vis_right << 1) + order;
		};
		// order = 0 ==> going right
		dp[conv(0, 0, 0)][0] = 0;
		dp[conv(0, 0, 1)][m] = 0;
		for (int i = 1; i <= n; i++) {
			vector<vector<int>> dp2(8, vector<int>(m+1, INF));
			vector<bool> vleft(m+1), vright(m+1);
			vector<int> pref(m+1, !A ? INF : -1), suff(m+1, !A ? -1 : INF);
			for (int j = 1; j <= m; j++) {
				vleft[j] = (a[i][j] == (A ? mn : mx)) || vleft[j-1];
				if (!A) pref[j] = min(a[i][j], pref[j-1]);
				else pref[j] = max(a[i][j], pref[j-1]);
			}
			for (int j = m-1; j >= 0; j--) {
				vright[j] = (a[i][j+1] == (A ? mx : mn)) || vright[j+1];
				if (!A) suff[j] = max(a[i][j+1], suff[j+1]);
				else suff[j] = min(a[i][j+1], suff[j+1]);
			}
			if (!A) { // maximize for left, minimize for right
				pref[0] = mx, suff[m] = mn;
			}
			else {
				pref[0] = mn, suff[m] = mx;
			}
			for (int j = 0; j < 8; j++) {
				const auto& [vis_left, vis_right, order] = vals[j];
				vector<int> pref_mn(m+1), suff_mn(m+1);
				for (int k = 0; k <= m; k++) {
					pref_mn[k] = min(dp[j][k], k ? pref_mn[k-1] : INF);
				}
				for (int k = m; k >= 0; k--) {
					suff_mn[k] = min(dp[j][k], k+1 <= m ? suff_mn[k+1] : INF);
				}
				for (int k = 0; k <= m; k++) {
					auto calc = [&]() {
						if (!A) return max(mx - pref[k], suff[k] - mn);
						return max(pref[k] - mn, mx - suff[k]);
					};
					if (!order) {
						ckmin(dp2[conv(vis_left | vleft[k], vis_right | vright[k], order)][k], max(pref_mn[k], calc()));
					}
					else {
						ckmin(dp2[conv(vis_left | vleft[k], vis_right | vright[k], order)][k], max(suff_mn[k], calc()));
					}
				}
			}
			swap(dp, dp2);
		}
		for (int i = 0; i < 2; i++) {
			ckmin(ans, *min_element(all(dp[conv(1, 1, i)])));
		}
	}
	cout << ans << '\n';


}
int main() {
    cin.tie(0)->sync_with_stdio(0);
    int t = 1;
//    cin >> t;
    while (t--) test_case();
}

#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...