이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#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) {
return 0;
// 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... |