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... |