제출 #709827

#제출 시각아이디문제언어결과실행 시간메모리
709827Cyanmond자리 배치 (IOI18_seats)C++17
33 / 100
1183 ms73124 KiB
#include "seats.h" #include <bits/stdc++.h> template <class M> class LazySegmentTree { using T = typename M::T; using L = typename M::L; int n, size, logn; std::vector<T> data; std::vector<L> lazy; void update(int i) { data[i] = M::op(data[2 * i], data[2 * i + 1]); } void all_apply(int i, const L &f) { data[i] = M::map(f, data[i]); if (i < size) lazy[i] = M::composite(f, lazy[i]); } void push(int i) { all_apply(2 * i, lazy[i]); all_apply(2 * i + 1, lazy[i]); lazy[i] = M::id(); } public: LazySegmentTree() {} LazySegmentTree(const std::vector<T> &vec) { n = (int)vec.size(); logn = 1; while ((1 << logn) < n) ++logn; size = 1 << logn; data.assign(2 * size, M::e()); std::copy(vec.begin(), vec.end(), data.begin() + size); for (int i = size - 1; i >= 1; --i) update(i); lazy.assign(size, M::id()); } void apply(int l, int r, const L &f) { l += size; r += size; for (int d = logn; d >= 1; --d) { if (((l >> d) << d) != l) push(l >> d); if (((r >> d) << d) != r) push((r - 1) >> d); } int l2 = l, r2 = r; while (l < r) { if (l & 1) all_apply(l++, f); if (r & 1) all_apply(--r, f); l /= 2; r /= 2; } l = l2; r = r2; for (int d = 1; d <= logn; ++d) { if (((l >> d) << d) != l) update(l >> d); if (((r >> d) << d) != r) update((r - 1) >> d); } } T fold(int l, int r) { l += size; r += size; for (int d = logn; d >= 1; --d) { if (((l >> d) << d) != l) push(l >> d); if (((r >> d) << d) != r) push((r - 1) >> d); } T pl = M::e(), pr = M::e(); while (l < r) { if (l & 1) pl = M::op(pl, data[l++]); if (r & 1) pr = M::op(data[--r], pr); l /= 2; r /= 2; } return M::op(pl, pr); } }; constexpr int inf = 1 << 30; struct MCountMin { struct T { int mn, cnt; }; static T op(T a, T b) { if (a.mn == b.mn) return {a.mn, a.cnt + b.cnt}; return a.mn < b.mn ? a : b; } static T e() { return {inf, 0}; } struct L { int ad; }; static T map(L a, T b) { return {b.mn + a.ad, b.cnt}; } static L composite(L a, L b) { return {a.ad + b.ad}; } static L id() { return {0}; } }; template <class M> class SegmentTree { using T = typename M::T; int n, size; std::vector<T> data; void update(int i) { data[i] = M::op(data[2 * i], data[2 * i + 1]); } public: SegmentTree() {} SegmentTree(const std::vector<T> &vec) { n = (int)vec.size(); size = 1; while (size < n) { size *= 2; } data.assign(2 * size, M::e()); std::copy(vec.begin(), vec.end(), data.begin() + size); for (int i = size - 1; i >= 1; --i) update(i); } void set(int i, const T &v) { i += size; data[i] = v; while (i != 1) { i /= 2; update(i); } } T fold(int l, int r) { T pl = M::e(), pr = M::e(); for (l += size, r += size; l < r; l /= 2, r /= 2) { if (l & 1) pl = M::op(pl, data[l++]); if (r & 1) pr = M::op(data[--r], pr); } return M::op(pl, pr); } }; struct MonoidMinMax { using T = std::pair<int, int>; static T op(const T &a, const T &b) { return {std::min(a.first, b.first), std::max(a.second, b.second)}; } static T e() { return {inf, -1}; } }; int H, W; std::vector<int> R, C; // SegmentTree<MonoidMinMax> rowSeg, colSeg; LazySegmentTree<MCountMin> seg; std::vector<std::set<int>> rowIds, colIds; std::vector<std::pair<int, bool>> firstIds; std::vector<int> times; void give_initial_chart(int h, int w, std::vector<int> r, std::vector<int> c) { H = h; W = w; R = r; C = c; assert(H == 1); times.resize(W); for (int i = 0; i < W; ++i) { times[c[i]] = i; } seg = LazySegmentTree<MCountMin>(std::vector<typename MCountMin::T>(W, {0, 1})); for (int i = -1; i < W; ++i) { int x = i == -1 ? W : times[i], y = i == W - 1 ? W : times[i + 1]; if (x > y) std::swap(x, y); seg.apply(x, y, {1}); } /* rowSeg = SegmentTree<MonoidMinMax>(rInit); colSeg = SegmentTree<MonoidMinMax>(cInit); rowIds.resize(H); colIds.resize(W); for (int i = 0; i < H * W; ++i) { if (colIds[C[i]].empty()) { firstIds.push_back({i, false}); } colIds[C[i]].insert(i); if (rowIds[R[i]].empty()) { firstIds.push_back({i, true}); } rowIds[R[i]].insert(i); } */ } void updRow(int i, int v, bool b) { if (not rowIds[i].empty()) { int mi = *rowIds[i].begin(); auto itr = std::find(firstIds.begin(), firstIds.end(), std::make_pair(mi, true)); firstIds.erase(itr); } if (b) rowIds[i].insert(v); else rowIds[i].erase(v); if (rowIds[i].empty()) return; int mi = *rowIds[i].begin(); auto itr = std::lower_bound(firstIds.begin(), firstIds.end(), std::make_pair(mi, true)); firstIds.insert(itr, {mi, true}); } void updCol(int i, int v, bool b) { if (not colIds[i].empty()) { int mi = *colIds[i].begin(); auto itr = std::find(firstIds.begin(), firstIds.end(), std::make_pair(mi, false)); firstIds.erase(itr); } if (b) colIds[i].insert(v); else colIds[i].erase(v); if (colIds[i].empty()) return; int mi = *colIds[i].begin(); auto itr = std::lower_bound(firstIds.begin(), firstIds.end(), std::make_pair(mi, false)); firstIds.insert(itr, {mi, false}); } void eraseI(int i) { int x = i == -1 ? W : times[i], y = i == W - 1 ? W : times[i + 1]; if (x > y) std::swap(x, y); seg.apply(x, y, {-1}); } void addI(int i) { int x = i == -1 ? W : times[i], y = i == W - 1 ? W : times[i + 1]; if (x > y) std::swap(x, y); seg.apply(x, y, {1}); } int swap_seats(int a, int b) { // upd /* updRow(R[a], a, false); updCol(C[a], a, false); updRow(R[b], b, false); updCol(C[b], b, false); updRow(R[a], b, true); updCol(C[a], b, true); updRow(R[b], a, true); updCol(C[b], a, true); rowSeg.set(a, std::make_pair(R[b], R[b])); rowSeg.set(b, std::make_pair(R[a], R[a])); colSeg.set(a, std::make_pair(C[b], C[b])); colSeg.set(b, std::make_pair(C[a], C[a])); */ eraseI(C[a]); eraseI(C[a] - 1); eraseI(C[b]); eraseI(C[b] - 1); std::swap(times[C[a]], times[C[b]]); // std::swap(R[a], R[b]); std::swap(C[a], C[b]); addI(C[a]); addI(C[a] - 1); addI(C[b]); addI(C[b] - 1); const auto res = seg.fold(0, W); return res.cnt; // calc /* int answer = 0; int last = 0; for (const auto [i, b] : firstIds) { // at i - 1 if (last == i) { continue; } const auto x = rowSeg.fold(0, i), y = colSeg.fold(0, i); if ((x.second - x.first + 1) * (y.second - y.first + 1) == i) { ++answer; } last = i; } ++answer; */ }
#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...