This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include "seats.h"
#include <algorithm>
#include <cassert>
#include <iostream>
using namespace std;
const int INF = 1e8;
const int MX = 4e6 + 10; // maximum hw
int h, w, n;
vector<int> row, col;
int subtask = 6;
// SUBTASK 2
// SUBTASK 3
struct Segtree {
  int N, m;
  int b[MX], t[MX], l[MX], r[MX];
  void setSize(int sz) {
    N = sz, m = 1;
    while (m < N) m <<= 1;
  }
  Segtree(int sz) {setSize(sz);}
  Segtree() {}
  void build() {
    for (int i = 0; i < m; ++i) {
      if (i >= N) b[i] = l[i] = INF, t[i] = r[i] = -INF;
      else {
        b[m+i] = t[m+i] = row[i];
        l[m+i] = r[m+i] = col[i];
      }
    }
    for (int i = m-1; i > 0; --i) {
      b[i] = min(b[2*i], b[2*i+1]);
      t[i] = max(t[2*i], t[2*i+1]);
      l[i] = min(l[2*i], l[2*i+1]);
      r[i] = max(r[2*i], r[2*i+1]);
    }
  }
  void update(int i) {
    i += m;
    b[i] = t[i] = row[i-m];
    l[i] = r[i] = col[i-m];
    while (i > 1) {
      b[i>>1] = min(b[i], b[i^1]);
      t[i>>1] = max(t[i], t[i^1]);
      l[i>>1] = min(l[i], l[i^1]);
      r[i>>1] = max(r[i], r[i^1]);
      i >>= 1;
    }
  }
  pair<pair<int, int>, pair<int, int>> query(int left, int right) {
    int B = INF, T = -INF, L = INF, R = -INF;
    for (left += m, right += m; left < right; left >>= 1, right >>= 1) {
      if (left&1) {
        B = min(B, b[left]);
        T = max(T, t[left]);
        L = min(L, l[left]);
        R = max(R, r[left]);
        left++;
      }
      if (right&1) {
        --right;
        B = min(B, b[right]);
        T = max(T, t[right]);
        L = min(L, l[right]);
        R = max(R, r[right]);
      }
    }
    return {{B, T}, {L, R}};
  }
  int queryGreater(int type, int limit) { // first index with value past some limit
    if (type == 0 && b[1] >= limit) return N;
    if (type == 1 && t[1] <= limit) return N;
    if (type == 2 && l[1] >= limit) return N;
    if (type == 3 && r[1] <= limit) return N;
    int i = 1;
    while (i < m) {
      int left = false;
      if (type == 0 && b[2*i] < limit) left = true;
      else if (type == 1 && t[2*i] > limit) left = true;
      else if (type == 2 && l[2*i] < limit) left = true;
      else if (type == 3 && r[2*i] > limit) left = true;
      i <<= 1;
      if (!left) ++i;
    }
    return i-m;
  }
};
Segtree seg;
void give_initial_chart(int H, int W, vector<int> R, vector<int> C) {
  h = H, w = W, n = H*W, row = R, col = C;
  // if (n <= 10000) subtask = 2;
  // else if (h <= 1000 && w <= 1000) {
    subtask = 3;
    seg.setSize(n);
    seg.build();
  // } else subtask = 4;
}
int swap_seats(int A, int B) {
  // if (subtask == 2) {
  //   swap(row[A], row[B]);
  //   swap(col[A], col[B]);
  //   int beauty = 1;
  //   int b = row[0], t = row[0], l = col[0], r = col[0];
  //   for (int i = 1; i < n; ++i) {
  //     b = min(b, row[i]);
  //     t = max(t, row[i]);
  //     l = min(l, col[i]);
  //     r = max(r, col[i]);
  //     if ((t-b+1)*(r-l+1) == (i+1)) ++beauty;
  //   }
  //   return beauty;
  // } else {
    swap(row[A], row[B]);
    swap(col[A], col[B]);
    seg.update(A);
    seg.update(B);
    // main idea: sum of side lengths of good rectangles <= 2000 and strictly increasing
    int beauty = 0;
    int i = 0;
    while (i < n) {
      // i is the start of a new segment with equal sidelength sum
      // first find the sidelengths of the segment
      auto [p1, p2] = seg.query(0, i+1);
      auto [B, T] = p1; auto [L, R] = p2;
      
      // now let us find the end of the segment
      // i.e. find the first index after i with larger sidelength sum
      int nextB = seg.queryGreater(0, B);
      int nextT = seg.queryGreater(1, T);
      int nextL = seg.queryGreater(2, L);
      int nextR = seg.queryGreater(3, R);
      int j = min({nextB, nextT, nextL, nextR}); // start of next segment
      assert((T-B+1)*(R-L+1)-1 >= j-1);
      if ((T-B+1)*(R-L+1)-1 < j) ++beauty;
      i = j;
    }
    return beauty;
  // }
}
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |