Submission #1241089

#TimeUsernameProblemLanguageResultExecution timeMemory
1241089madamadam3Mosaic (IOI24_mosaic)C++20
22 / 100
781 ms302376 KiB
#include "mosaic.h"
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
using vi =vector<int>;
using vl = vector<ll>;
using vvi = vector<vi>;
using vvl = vector<vl>;
using pi = pair<int, int>;
using vpi = vector<pi>;

#ifdef LOCAL
  #define dout std::cout
#else
  #define dout if (0) std::cout
#endif

#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define all(x) (x).begin(), (x).end()
#define en(x) (x).end()
#define bg(x) (x).begin()
#define rev(x) reverse(all(x))
#define sz(x) int((x).size())
#define FOR(i, a, b) for (int i = a; i < b; i++)
#define each(a, x) for (auto &a : x)
#define trace(x) for (auto &el : x) dout << el << " "

vl mosaic(vi X, vi Y, vi T, vi B, vi L, vi R) {
  int Q = sz(T), n = sz(X);

  if (n <= 5000) {
    vl C(Q, 0);
    vvi grid(n, vi(n, 0));
    FOR(i, 0, n) {
      grid[0][i] = X[i];
      grid[i][0] = Y[i];
    }

    FOR(i, 1, n) {
      FOR(j, 1, n) {
        if (grid[i-1][j] == 0 && grid[i][j-1] == 0) grid[i][j] = 1;
        else grid[i][j] = 0;
      }
    }

    vvl pref(n+1, vl(n+1, 0));
    FOR(i, 0, n) {
      FOR(j, 0, n) {
        pref[i+1][j+1] = grid[i][j] + pref[i+1][j];
      }

      FOR(j, 0, n) {
        pref[i+1][j+1] += pref[i][j+1];
      }
    }

    // vl prefx(n+1, 0); FOR(i, 0, n) prefx[i+1] = prefx[i] + X[i];
    FOR(qn, 0, Q) {
      int x1 = T[qn], x2 = B[qn], y1 = L[qn], y2 = R[qn];
      // C[qn] = prefx[y2+1] - prefx[y1];
      C[qn] += pref[x2+1][y2+1];
      C[qn] += pref[x1][y1];
      C[qn] -= pref[x1][y2+1];
      C[qn] -= pref[x2+1][y1];
    }

    return C;
  }

  vl C(Q, 0);

  vvi grid(n, vi(3, 0)); grid[0].resize(n); grid[1].resize(n); grid[2].resize(n);
  FOR(i, 0, n) {
    grid[0][i] = X[i];
    grid[i][0] = Y[i];
  }

  map<pi, int> coord;
  map<int, pi> revcoord;
  int cc = 0;
  for (int i = n - 1; i >= 3; i--) {
    coord[{i, 2}] = cc++;
    revcoord[cc-1] = {i, 2};
  }
  for (int i = 2; i < n; i++) {
    coord[{2, i}] = cc++;
    revcoord[cc-1] = {2, i};
  }

  FOR(i, 1, n) {
    int top = i <= 2 ? n : 3;
    FOR(j, 1, top) {
      if (grid[i-1][j] == 0 && grid[i][j-1] == 0) grid[i][j] = 1;
      else grid[i][j] = 0;
    }
  }

  vl pref(cc+1, 0);
  FOR(i, 0, cc) pref[i+1] = pref[i] + grid[revcoord[i].first][revcoord[i].second];
  vl wpref(cc+1, 0); FOR(i, 1, cc+1) wpref[i] = wpref[i-1] + i * grid[revcoord[i-1].first][revcoord[i-1].second];
  vl wrpref(cc+1, 0); FOR(i, 1, cc+1) wrpref[i] = wrpref[i-1] + i * grid[revcoord[cc-i].first][revcoord[cc-i].second];

  vvl prefix(n+1, vl(4, 0)); prefix[0].resize(n+1); prefix[1].resize(n+1); prefix[2].resize(n+1); prefix[3].resize(n+1);
  FOR(i, 0, n) {
    int top = i < 3 ? n : 3;
    FOR(j, 0, top) {
      prefix[i+1][j+1] = grid[i][j] + prefix[i+1][j];
    }

    FOR(j, 0, top) {
      prefix[i+1][j+1] += prefix[i][j+1];
    }
  }

  auto get_ramp_up = [&](int u, int len) {
    int v = u + len - 1;
    ll sumVal   = pref[v+1] - pref[u];
    ll sum_iVal = (wpref[v+1] - wpref[u]) - sumVal;
    return sum_iVal - ll(u-1) * sumVal;
  };

  auto get_ramp_down = [&](int e, int len) {
    int s = e - len + 1;
    ll sumVal   = pref[e+1] - pref[s];
    ll sum_iVal = (wpref[e+1] - wpref[s]) - sumVal;
    return sum_iVal + ll(len - e) * sumVal;
  };

  for (int qn = 0; qn < Q; ++qn) {
    int x1 = T[qn], x2 = B[qn];
    int y1 = L[qn], y2 = R[qn];
    ll res = 0;

    if (x1 <= 2) {
        int r = min(x2, 2);
        res += prefix[r+1][y2+1]
            - prefix[r+1][y1]
            - prefix[x1][y2+1]
            + prefix[x1][y1];
    }
    if (y1 <= 2) {
        int c = min(y2, 2);
        res += prefix[x2+1][c+1]
            - prefix[x1][c+1]
            - prefix[x2+1][y1]
            + prefix[x1][y1];
    }
    if (x1 <= 2 && y1 <= 2) {
        res -= prefix[x1][y1];
    }

    int cx = max(x1, 3), cy = max(y1, 3);
    if (cx <= x2 && cy <= y2) {
      int diagLen = min(x2 - cx, y2 - cy) + 1;
      int sx = cx - (diagLen - 1),
          sy = cy - (diagLen - 1);
      int ex = cx, ey = cy;
      int lc = coord[{sx, sy}],
          rc = coord[{ex, ey}];

      ll rise = get_ramp_up(lc, diagLen);

      ll flat = 0;
      int fl = lc + diagLen,
          fr = rc - diagLen;
      if (fl <= fr) {
          ll cnt    = fr - fl + 1;
          ll segment= pref[fr+1] - pref[fl];
          flat = cnt * segment;
      }

      ll fall = get_ramp_down(rc, diagLen);

      res += rise + flat + fall;
    }

    C[qn] = res;
  }

  return C;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...