Submission #602432

#TimeUsernameProblemLanguageResultExecution timeMemory
602432erekleSeats (IOI18_seats)C++17
31 / 100
4038 ms118864 KiB
#include "seats.h" #include <algorithm> #include <cassert> #include <iostream> #include <set> 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; // SUBTASK 4 set<int> good; void findGood(int l, int r) { // range [l, r) set<int>::iterator it = good.lower_bound(l); while (it != good.end() && *it < r) it = good.erase(it); for (int i = l; i < r; ++i) { // find the sidelengths of the segment auto [p1, p2] = seg.query(0, i+1); auto [B, T] = p1; auto [L, R] = p2; if ((T-B+1)*(R-L+1)-1 == i) good.insert(i); } } 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; seg.setSize(n); seg.build(); findGood(0, n); } } 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 if (subtask == 3) { 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; } else { // Subtask 4 swap(row[A], row[B]); swap(col[A], col[B]); seg.update(A); seg.update(B); if (A > B) swap(A, B); findGood(A, B); return good.size(); } }
#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...