#include using namespace std; using pii = pair; using ll = long long; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int N, M; long long C; int X; if(!(cin >> N >> M >> C >> X)) return 0; vector> A(N, vector(M)); long long lo = (1LL<<60), hi = -(1LL<<60); for(int i=0;i> A[i][j]; lo = min(lo, A[i][j]); hi = max(hi, A[i][j]); } } // search range: possible min beauty between lo-C and hi long long L = - (1LL<<60), R = hi; // we binary search T in [L, R] // But safe to set L = lo - C (lower bound), R = hi. L = lo - C; long long ans = L; auto feasible = [&](long long T)->bool{ // build usable/fragile/robust vector> usable(N, vector(M, 0)); vector> fragile(N, vector(M, 0)); vector> robust(N, vector(M, 0)); for(int i=0;i= T){ usable[i][j] = 1; if(A[i][j] - C >= T){ robust[i][j] = 1; } else { fragile[i][j] = 1; } } } } // If any position has zero usable types -> impossible for(int i=0;i set of possible run lengths). We store as vector or vector. // Because X might be up to N, but we keep small memory by using unordered_set or bitset per color. // We'll implement as vector> cur(M, vector(X+1)) for(int start=0; start> cur(M, vector(X+1, 0)); cur[start][1] = 1; // propagate positions 1..N-1 for(int i=1;i> nxt(M, vector(X+1, 0)); for(int prev_color=0; prev_color break early bool any=false; for(int q=0;q always fine, but also must ensure pos0 fragile still ok w.r.t pos1 (that was enforced earlier), and posN-1 fragile w.r.t posN-2 was enforced earlier. The wrap is different so no extra constraint. // - if end_color == start: combined run = start_run(=1) + end_run must be <= X, AND pos0 and posN-1 must allow adjacency: // * pos0: if fragile[0][start] then it disallows any neighbor same -> cannot have posN-1 same. // * posN-1: if fragile[N-1][start] then it disallows neighbor same -> cannot have pos0 same. bool ok_any = false; for(int end_color=0; end_color fine. ok_any = true; break; } else { // same color across wrap: if(1 + end_run <= X){ // but fragility at pos0 or posN-1 may forbid adjacency if(fragile[0][start]) continue; // pos0 cannot have same neighbor if(fragile[N-1][start]) continue; // Also need to ensure that positions contributing to runs had robustness where adjacency exists. // Those were enforced in DP for internal adjacencies. For wrap, adjacency between posN-1 and pos0 means pos0's adjacency with posN-1 must be allowed: // pos0 adjacency to same was not enforced earlier (we only enforced pos0 vs pos1 indirectly), // but we already checked fragile[0] above. For posN-1, if it was counted as part of end_run>1 then posN-1 needed robust (checked). If end_run==1 and posN-1 had same neighbor posN-2? that's already handled. ok_any = true; break; } } } } if(ok_any) return true; } return false; }; // binary search for maximum T with feasible(T) == true long long low = L, high = R; while(low <= high){ long long mid = (low + high) / 2; if(feasible(mid)){ ans = mid; low = mid + 1; } else { high = mid - 1; } } cout << ans << "\n"; return 0; }