mitkonikov

Binary Search on a Fenwick in log2(N) time

Mar 5th, 2023 (edited)
676
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.12 KB | None | 1 0
  1. #include <bits/stdc++.h>
  2. #define ll long long
  3.  
  4. using namespace std;
  5.  
  6. struct FenwickTree {
  7.     vector<int> fwt;
  8.     int LOGN = 0;
  9.  
  10.     FenwickTree(int n) {
  11.         fwt.resize(n, 0);
  12.         LOGN = log2(n) + 2;
  13.     }
  14.  
  15.     void add(int ind, int val = 1) {
  16.         for (ind++; ind < fwt.size(); ind += ind & -ind) fwt[ind] += val;
  17.     }
  18.  
  19.     int get(int ind) {
  20.         int s = 0;
  21.         for (ind++; ind > 0; ind -= ind & -ind) s += fwt[ind];
  22.         return s;
  23.     }
  24.  
  25.     int bit_search(int v) {
  26.         v++;
  27.         int sum = 0;
  28.         int pos = 0;
  29.  
  30.         for (int i = LOGN; i >= 0; i--) {
  31.             if (pos + (1 << i) < fwt.size() && sum + fwt[pos + (1 << i)] < v) {
  32.                 sum += fwt[pos + (1 << i)];
  33.                 pos += (1 << i);
  34.             }
  35.         }
  36.  
  37.         return pos;
  38.     }
  39. };
  40.  
  41. int main() {
  42.     cin.tie(0)->sync_with_stdio(0);
  43.     int N, K;
  44.     cin >> N >> K;
  45.     vector<vector<int>> A(N, vector<int>(N, 0));
  46.     vector<vector<int>> B(N, vector<int>(N, 0));
  47.     vector<int> comp;
  48.     for (int i = 0; i < N; i++) {
  49.         for (int j = 0; j < N; j++) {
  50.             cin >> A[i][j];
  51.             comp.push_back(A[i][j]);
  52.         }
  53.     }
  54.     // index compression
  55.     sort(comp.begin(), comp.end());
  56.     auto getCompressed = [&](int a) {
  57.         return lower_bound(comp.begin(), comp.end(), a) - comp.begin() + 1;
  58.     };
  59.  
  60.     auto uncompress = [&](int a) { return comp[a]; };
  61.  
  62.     for (int i = 0; i < N; i++) {
  63.         for (int j = 0; j < N; j++) {
  64.             B[i][j] = getCompressed(A[i][j]);
  65.         }
  66.     }
  67.  
  68.     FenwickTree fwt(N * N + 100);
  69.     int ans = INT_MAX;
  70.     auto updateAns = [&]() {
  71.         ans = min(ans, comp[fwt.bit_search((K * K) / 2) - 1]);
  72.     };
  73.  
  74.     for (int j = 0; j < K; j++) {
  75.         for (int k = 0; k < K; k++) {
  76.             // add A[i+j][k]
  77.             fwt.add(B[j][k], 1);
  78.         }
  79.     }
  80.     updateAns();
  81.  
  82.     for (int i = 0; i < N - K + 1; i++) {
  83.         if (i % 2 == 0) {
  84.             // shift to the right
  85.             for (int k = 0; k + K < N; k++) {
  86.                 for (int j = 0; j < K; j++) {
  87.                     fwt.add(B[i + j][k], -1);
  88.                     fwt.add(B[i + j][k + K], 1);
  89.                 }
  90.                 updateAns();
  91.             }
  92.  
  93.             if (i + K >= N) break;
  94.  
  95.             // shift down at the end
  96.             for (int col = 0; col < K; col++) {
  97.                 fwt.add(B[i][N - 1 - col], -1);
  98.                 fwt.add(B[i + K][N - 1 - col], 1);
  99.             }
  100.  
  101.             updateAns();
  102.         } else {
  103.             // shift to the left
  104.             for (int k = N - 1; k - K >= 0; k--) {
  105.                 for (int j = 0; j < K; j++) {
  106.                     fwt.add(B[i + j][k], -1);
  107.                     fwt.add(B[i + j][k - K], 1);
  108.                 }
  109.                 updateAns();
  110.             }
  111.  
  112.             if (i + K >= N) break;
  113.             // shift down at the start
  114.             for (int col = 0; col < K; col++) {
  115.                 fwt.add(B[i][col], -1);
  116.                 fwt.add(B[i + K][col], 1);
  117.             }
  118.  
  119.             updateAns();
  120.         }
  121.     }
  122.     cout << ans << endl;
  123.     return 0;
  124. }
Advertisement
Add Comment
Please, Sign In to add comment