ABC 203 D - Pond
阿新 • • 發佈:2022-05-23
D - Pond
二分 + 字首和
求一個子矩陣中元素的中位數,可二分中位數,check 過程中將矩陣變為 01 矩陣,若小於 mid 則為 1,用二維字首和求出有多少元素小於 mid
複雜度 \(O(n^2log(max(A_i)))\)
注意二分求中位數的細節
- 若有 \(n\) 個數,則中位數為第 \(\lceil \frac n2\rceil\) 小的元素
- 令 \(t=\lceil \frac n2\rceil-1\), 若有 \(cnt\) 個元素小於 mid, 返回 \(cnt<=t\)
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <cmath> using namespace std; typedef long long ll; const int N = 8e2 + 10; int n, k, t; int a[N][N], s[N][N]; bool check(int x) { for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + (a[i][j] < x); int cnt = 0; for (int sx = 1; sx + k - 1 <= n; sx++) { for (int sy = 1; sy + k - 1 <= n; sy++) { int ex = sx + k - 1, ey = sy + k - 1; cnt = max(cnt, s[ex][ey] - s[sx-1][ey] - s[ex][sy-1] + s[sx-1][sy-1]); } } return cnt <= t; } int main() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); cin >> n >> k; t = (k * k + 1) / 2 - 1;//小於中位數的有t個 for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) cin >> a[i][j]; int l = 0, r = 1e9 + 1; while(l + 1 != r) { int mid = l + r >> 1; if (check(mid)) l = mid; else r = mid; } cout << l << endl; return 0; }