Submission #1030399

#TimeUsernameProblemLanguageResultExecution timeMemory
1030399shiomusubi496Ancient Books (IOI17_books)C++17
100 / 100
680 ms375416 KiB
#include "books.h" #include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (int)(n); ++i) #define rep2(i, a, b) for (int i = (int)(a); i < (int)(b); ++i) #define rrep(i, n) for (int i = (int)(n) - 1; i >= 0; --i) #define rrep2(i, a, b) for (int i = (int)(b) - 1; i >= (int)(a); --i) #define all(v) begin(v), end(v) #define rall(v) rbegin(v), rend(v) using namespace std; using ll = long long; constexpr ll inf = 1e18; template<class T, class U> bool chmin(T& a, const U& b) { return a > b ? a = b, true : false; } template<class T, class U> bool chmax(T& a, const U& b) { return a < b ? a = b, true : false; } template<class M> class SparseTable { using T = typename M::T; int n; vector<vector<T>> dat; public: SparseTable(vector<T> a) { n = a.size(); int h = __lg(n + 1) + 1; dat.assign(h + 1, vector<T>(n, M::id())); rep (i, n) dat[0][i] = a[i]; rep (i, h) rep (j, n - (1 << i)) { dat[i + 1][j] = M::op(dat[i][j], dat[i][j + (1 << i)]); } } T prod(int l, int r) const { assert(0 <= l && l <= r && r <= n); int b = __lg(r - l); return M::op(dat[b][l], dat[b][r - (1 << b)]); } template<class F> int max_right(int l, F f) const { assert(0 <= l && l <= n); assert(f(M::id())); if (l == n) return n; int ok = l, ng = n + 1; while (ng - ok > 1) { int m = (ok + ng) / 2; (f(prod(l, m)) ? ok : ng) = m; } return ok; } template<class F> int min_left(int r, F f) const { assert(0 <= r && r <= n); assert(f(M::id())); if (r == 0) return 0; int ok = r, ng = -1; while (ok - ng > 1) { int m = (ok + ng) / 2; (f(prod(m, r)) ? ok : ng) = m; } return ok; } }; template<class M> class SegmentTree { using T = typename M::T; int n; vector<T> dat; public: SegmentTree(vector<T> a) { n = 1; while (n < a.size()) n <<= 1; dat.assign(n << 1, M::id()); rep (i, a.size()) dat[i + n] = a[i]; for (int i = n - 1; i >= 1; --i) { dat[i] = M::op(dat[i << 1], dat[i << 1 | 1]); } } T prod(int l, int r) const { assert(0 <= l && l <= r && r <= n); T res1 = M::id(), res2 = M::id(); for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l & 1) res1 = M::op(res1, dat[l++]); if (r & 1) res2 = M::op(dat[--r], res2); } return M::op(res1, res2); } void set(int k, T x) { k += n; dat[k] = x; while (k > 1) { k /= 2; dat[k] = M::op(dat[k << 1], dat[k << 1 | 1]); } } }; struct Min { using T = ll; static T op(T a, T b) { return min(a, b); } static T id() { return inf; } }; struct Max { using T = ll; static T op(T a, T b) { return max(a, b); } static T id() { return -inf; } }; long long minimum_walk(std::vector<int> p, int s) { int n = p.size(); if (is_sorted(all(p))) return 0; ll ans = 0; { while (p.back() == n - 1) { if (s == n - 1) { --s; ans += 2; } p.pop_back(); --n; } reverse(all(p)); rep (i, n) p[i] = n - 1 - p[i]; s = n - 1 - s; while (p.back() == n - 1) { if (s == n - 1) { --s; ans += 2; } p.pop_back(); --n; } reverse(all(p)); rep (i, n) p[i] = n - 1 - p[i]; s = n - 1 - s; } rep (i, n) ans += abs(p[i] - i); vector<ll> mns(n), mxs(n); { vector<bool> seen(n); rep (i, n) { if (seen[i]) continue; int j = i; int mx = 0; do { seen[j] = true; chmax(mx, j); j = p[j]; } while (i != j); j = i; do { mns[j] = i; mxs[j] = mx; j = p[j]; } while (i != j); } } { vector<bool> seen(n, false); SegmentTree<Min> seg1(mns); SegmentTree<Max> seg2(mxs); rep (i, n) { if (seen[i]) continue; int l = mns[i], r = mxs[i]; while (1) { int l2 = seg1.prod(l, r + 1); int r2 = seg2.prod(l, r + 1); if (l == l2 && r == r2) break; l = l2; r = r2; } int j = i; do { seen[j] = true; mns[j] = l; mxs[j] = r; seg1.set(j, l); seg2.set(j, r); j = p[j]; } while (i != j); } } SparseTable<Min> st1(mns); SparseTable<Max> st2(mxs); // rep (i, n) cout << mns[i] << " \n"[i == n - 1]; // rep (i, n) cout << mxs[i] << " \n"[i == n - 1]; // cout << ans << endl; int l = mns[s], r = mxs[s]; while (l != 0 || r != n - 1) { int l2 = st2.min_left(l, [&](ll x) { return x <= r; }); int r2 = st1.max_right(r + 1, [&](ll x) { return x >= l; }) - 1; if (l2 == 0 && l != 0) { ans += 2; l = mns[l - 1]; } else if (r2 == n - 1 && r != n - 1) { ans += 2; r = mxs[r + 1]; } else { int cnt1 = 0, cnt2 = 0; while (l > l2) { ++cnt1; l = mns[l - 1]; } while (r < r2) { ++cnt2; r = mxs[r + 1]; } ans += (min(cnt1, cnt2) + 1) * 2; l = mns[max<int>(l2 - 1, 0)]; r = mxs[min<int>(r2 + 1, n - 1)]; } } return ans; }

Compilation message (stderr)

books.cpp: In instantiation of 'SegmentTree<M>::SegmentTree(std::vector<typename M::T>) [with M = Min; typename M::T = long long int]':
books.cpp:163:34:   required from here
books.cpp:75:18: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   75 |         while (n < a.size()) n <<= 1;
      |                ~~^~~~~~~~~~
books.cpp: In instantiation of 'SegmentTree<M>::SegmentTree(std::vector<typename M::T>) [with M = Max; typename M::T = long long int]':
books.cpp:164:34:   required from here
books.cpp:75:18: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
#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...