Hướng dẫn giải của Bedao OI Contest 3 - Vụ trộm thế kỷ
Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Đầu tiên chúng ta có thể mô phỏng đường đi laser vào mê cung. Việc này có thể làm trong ~O(Nlog(N))~ (với ~N~ là tổng số gương trong mê cung) bằng cách lưu những vị trí gương trên các hàng và cột. Việc này có thể biểu diễn bằng các đoạn thẳng dọc và ngang.
Nếu laser đi ra khỏi mê cung, in ra ~0~. Ngược lại, ta mô phỏng ~1~ laser đi ngược từ điểm cuối của bảng tương tự như trên. Nhận xét: những điểm đặt gương hợp lệ là giao của 2 tia laser. Sử dụng sweepline để đếm và tìm điểm giao có thứ tự từ điển nhỏ nhất(sử dụng data structure như segment tree hoặc fenwick tree để đếm). Nếu số điểm giao bằng ~0~ thì in ra ~impossible~. Tổng độ phức tạp: ~O(Nlog(N))~
/************************************* * author: marvinthang * * created: 17.07.2023 11:03:12 * *************************************/ #include <bits/stdc++.h> using namespace std; #define fi first #define se second #define left ___left #define right ___right #define TIME (1.0 * clock() / CLOCKS_PER_SEC) #define MASK(i) (1LL << (i)) #define BIT(x, i) ((x) >> (i) & 1) #define __builtin_popcount __builtin_popcountll #define ALL(v) (v).begin(), (v).end() #define REP(i, n) for (int i = 0, _n = (n); i < _n; ++i) #define REPD(i, n) for (int i = (n); i--; ) #define FOR(i, a, b) for (int i = (a), _b = (b); i < _b; ++i) #define FORD(i, b, a) for (int i = (b), _a = (a); --i >= _a; ) #define FORE(i, a, b) for (int i = (a), _b = (b); i <= _b; ++i) #define FORDE(i, b, a) for (int i = (b), _a = (a); i >= _a; --i) #define scan_op(...) istream & operator >> (istream &in, __VA_ARGS__ &u) #define print_op(...) ostream & operator << (ostream &out, const __VA_ARGS__ &u) #ifdef LOCAL #include "debug.h" #else #define file(name) if (fopen(name".inp", "r")) { freopen(name".inp", "r", stdin); freopen(name".out", "w", stdout); } #define DB(...) 23 #define db(...) 23 #define debug(...) 23 #endif template <class U, class V> scan_op(pair <U, V>) { return in >> u.first >> u.second; } template <class T> scan_op(vector <T>) { for (size_t i = 0; i < u.size(); ++i) in >> u[i]; return in; } template <class U, class V> print_op(pair <U, V>) { return out << '(' << u.first << ", " << u.second << ')'; } template <size_t i, class T> ostream & print_tuple_utils(ostream &out, const T &tup) { if constexpr(i == tuple_size<T>::value) return out << ")"; else return print_tuple_utils<i + 1, T>(out << (i ? ", " : "(") << get<i>(tup), tup); } template <class ...U> print_op(tuple<U...>) { return print_tuple_utils<0, tuple<U...>>(out, u); } template <class Con, class = decltype(begin(declval<Con>()))> typename enable_if <!is_same<Con, string>::value, ostream&>::type operator << (ostream &out, const Con &con) { out << '{'; for (__typeof(con.begin()) it = con.begin(); it != con.end(); ++it) out << (it == con.begin() ? "" : ", ") << *it; return out << '}'; } // end of template const int MAX = 1e6 + 6; int R, C, M, N; set <pair <int, int>> sx[MAX], sy[MAX]; void init(void) { cin >> R >> M >> N; FORE(i, 1, R) sx[i].clear(); FORE(i, 1, C) sy[i].clear(); REP(i, M) { int x, y; cin >> y >> x; sx[x].emplace(y, 0); sy[y].emplace(x, 0); } REP(i, N) { int x, y; cin >> y >> x; sx[x].emplace(y, 1); sy[y].emplace(x, 1); } } using t4 = tuple <int, int, int, int>; // index from 0 template <class T = int> struct Fenwick { T *bit = nullptr; int n; Fenwick(int _n = 0) { resize(_n); } void reset(void) { fill(bit, bit + 1 + n, T(0)); } void resize(int _n) { if (bit != nullptr) delete[] bit; n = _n; bit = new T[n + 1]; reset(); } void update(int i, T val) { assert(0 <= i); ++i; for (; i <= n; i += i & -i) bit[i] += val; } T get(int i) { if (i < 0) return T(0); ++i; i = min(i, n); T res(0); for (; i > 0; i -= i & -i) res += bit[i]; return res; } int upper_bound(T val) { int res = 0; for (int i = __lg(n); i >= 0; --i) { if ((res | MASK(i)) <= n && val >= bit[res | MASK(i)]) { res |= MASK(i); val -= bit[res]; } } return res; } int lower_bound(T val) { int res = 0; for (int i = __lg(n); i >= 0; --i) { if ((res | MASK(i)) <= n && val > bit[res | MASK(i)]) { res |= MASK(i); val -= bit[res]; } } return res; } }; vector <t4> go(int x, int y, int dir) { vector <t4> lines; while (true) { if (!dir) { auto it = sx[x].lower_bound(make_pair(y, 2)); if (it == sx[x].end()) { lines.emplace_back(x, y, C + 1, 0); break; } lines.emplace_back(x, y, it->fi, 0); y = it->fi; dir = it->se ? 1 : 3; } else if (dir == 1) { auto it = sy[y].lower_bound(make_pair(x, 2)); if (it == sy[y].end()) { lines.emplace_back(y, x, R + 1, 1); break; } lines.emplace_back(y, x, it->fi, 1); x = it->fi; dir = it->se ? 0 : 2; } else if (dir == 2) { auto it = sx[x].lower_bound(make_pair(y, 0)); if (it == sx[x].begin()) { lines.emplace_back(x, y, 0, 0); break; } --it; lines.emplace_back(x, y, it->fi, 0); y = it->fi; dir = it->se ? 3 : 1; } else { auto it = sy[y].lower_bound(make_pair(x, 0)); if (it == sy[y].begin()) { lines.emplace_back(y, x, 0, 1); break; } --it; lines.emplace_back(y, x, it->fi, 1); x = it->fi; dir = it->se ? 2 : 0; } } return lines; } void process(void) { vector <t4> ls = go(0, 1, 1); auto [x, l, r, t] = ls.back(); if (t == 1 && x == C && r == R + 1) return void(cout << 0); vector <t4> lt = go(R + 1, C, 3); vector <t4> events; for (auto &[x, l, r, t]: ls) { if (l > r) swap(l, r); ++l; --r; if (!t && l <= r) { events.emplace_back(l, 0, x, +1); events.emplace_back(r + 1, 0, x, -1); } } for (auto &[x, l, r, t]: lt) { if (l > r) swap(l, r); ++l; --r; if (t && l <= r) events.emplace_back(x, 1, l, r); } sort(ALL(events)); Fenwick <int> bit(R + 1); long long cnt = 0; pair <int, int> min_pos(C + 1, R + 1); for (auto [x, t, l, r]: events) { if (!t) bit.update(l, r); else { int a = bit.get(r); int b = bit.get(l - 1); cnt += a - b; if (a > b) { int p = bit.upper_bound(b); min_pos = min(min_pos, make_pair(x, p)); } } } events.clear(); for (auto [x, l, r, t]: ls) if (t && l <= r) events.emplace_back(x, 1, l, r); for (auto [x, l, r, t]: lt) if (!t && l <= r) { events.emplace_back(l, 0, x, +1); events.emplace_back(r + 1, 0, x, -1); } sort(ALL(events)); for (auto [x, t, l, r]: events) { if (!t) bit.update(l, r); else { int a = bit.get(r); int b = bit.get(l - 1); cnt += a - b; if (a > b) { int p = bit.upper_bound(b); min_pos = min(min_pos, make_pair(x, p)); } } } if (!cnt) cout << "impossible"; else cout << cnt << ' ' << min_pos.fi << ' ' << min_pos.se; } int main(void) { ios_base::sync_with_stdio(false); cin.tie(nullptr); // cout.tie(nullptr); file("I"); int t = 0; while (cin >> C) { init(); process(); cout << '\n'; } cerr << "Time elapsed: " << TIME << " s.\n"; return (0^0); }
Bình luận