Submission #1030387

#TimeUsernameProblemLanguageResultExecution timeMemory
1030387shiomusubi496Ancient Books (IOI17_books)C++17
42 / 100
876 ms1048576 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 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); vector<vector<ll>> dp(n + 1, vector<ll>(n + 1, inf)); dp[s][s] = 0; rep (len, n) { rep (l, n + 1 - len) { int r = l + len; if (dp[l][r] == inf) continue; { int l2 = st1.prod(l, r + 1); int r2 = st2.prod(l, r + 1); chmin(dp[l2][r2], dp[l][r]); } if (l != 0) chmin(dp[mns[l - 1]][max<int>(r, mxs[l - 1])], dp[l][r] + 1); if (r != n - 1) chmin(dp[min<int>(l, mns[r + 1])][mxs[r + 1]], dp[l][r] + 1); } } return ans + dp[0][n - 1] * 2; }

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:141:34:   required from here
books.cpp:53:18: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   53 |         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:142:34:   required from here
books.cpp:53: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...