--- tags: IOI --- # IOI2010 Day1-3 住み心地 (Quality of Living) もう典型になってしまったんだなあ… ## 問題 https://www.ioi-jp.org/ioi/2010/tasks/tasks_jpn/day1/t3_quality/index.html https://oj.uz/problem/view/IOI10_quality $R \times C$ マスのグリッドがあり、各マスに $1$ から $RC$ の順列が割り当てられています。 $H \times W$ の矩形領域を選んだときの中央値 の最小値を求めてください。 $R,C ≤ 3000$ ## 考察 中央値の最小値 → 決め打ち二分探索 $\Theta(RC\log(RC))$ ## 実装 https://oj.uz/submission/245589 ```cpp #include <bits/stdc++.h> using namespace std; using pii = pair<int, int>; #define name3(a,b,c,d,...) d #define rep1(b) for(int i = 0; i < b; i++) #define rep2(i,b) for(int i = 0; i < b; i++) #define rep3(i,a,b) for(int i = a; i < b; i++) #define rep(...) name3(__VA_ARGS__,rep3,rep2,rep1)(__VA_ARGS__) int rectangle(int R, int C, int H, int W, int Q[3001][3001]){ auto check = [&](int x) -> bool { vector s(R + 1, vector<int>(C + 1)); rep(R) rep(j, C) s[i + 1][j + 1] = Q[i][j] <= x; rep(R + 1) rep(j, C) s[i][j + 1] += s[i][j]; rep(R) rep(j, C + 1) s[i + 1][j] += s[i][j]; rep(i, H, R + 1) rep(j, W, C + 1) if(s[i][j] - s[i - H][j] - s[i][j - W] + s[i - H][j - W] >= (H * W + 1) / 2) return true; return false; }; int ok = R * C, ng = 0; while(ok - ng > 1){ int cen = (ok + ng) / 2; (check(cen) ? ok : ng) = cen; } return ok; } ```