Submission #264555

#TimeUsernameProblemLanguageResultExecution timeMemory
264555KoDKoala Game (APIO17_koala)C++11
70 / 100
130 ms1244 KiB
/** * @title Template */ #include <iostream> #include <algorithm> #include <utility> #include <numeric> #include <vector> #include <array> #include <cassert> #include <stack> template <class T, class U> bool chmin(T &lhs, const U &rhs) { if (lhs > rhs) { lhs = rhs; return true; } return false; } template <class T, class U> bool chmax(T &lhs, const U &rhs) { if (lhs < rhs) { lhs = rhs; return true; } return false; } /** * @title Chmin/Chmax */ class range { public: class iterator { private: int64_t M_position; public: iterator(int64_t position) noexcept: M_position(position) { } void operator ++ () noexcept { ++M_position; } bool operator != (iterator other) const noexcept { return M_position != other.M_position; } int64_t operator * () const noexcept { return M_position; } }; class reverse_iterator { private: int64_t M_position; public: reverse_iterator(int64_t position) noexcept: M_position(position) { } void operator ++ () noexcept { --M_position; } bool operator != (reverse_iterator other) const noexcept { return M_position != other.M_position; } int64_t operator * () const noexcept { return M_position; } }; private: const iterator M_first, M_last; public: range(int64_t first, int64_t last) noexcept: M_first(first), M_last(std::max(first, last)) { } iterator begin() const noexcept { return M_first; } iterator end() const noexcept { return M_last; } reverse_iterator rbegin() const noexcept { return reverse_iterator(*M_last - 1); } reverse_iterator rend() const noexcept { return reverse_iterator(*M_first - 1); } }; /** * @title Range */ #include <type_traits> #include <iterator> template <class T> class rev_impl { public: using iterator = decltype(std::declval<T>().rbegin()); private: const iterator M_begin; const iterator M_end; public: rev_impl(T &&cont) noexcept: M_begin(cont.rbegin()), M_end(cont.rend()) { } iterator begin() const noexcept { return M_begin; } iterator end() const noexcept { return M_end; } }; template <class T> rev_impl<T> rev(T &&cont) { return rev_impl<T>(std::forward<T>(cont)); } /** * @title Reverser */ using i32 = int32_t; using i64 = int64_t; using u32 = uint32_t; using u64 = uint64_t; constexpr i32 inf32 = (i32(1) << 30) - 1; constexpr i64 inf64 = (i64(1) << 62) - 1; void playRound(i32 *B, i32 *R); i32 minValue(const i32 N, const i32 W); i32 maxValue(const i32 N, const i32 W); i32 greaterValue(const i32 N, const i32 W); void allValues(const i32 N, const i32 W, i32 *P); i32 minValue(const i32 N, const i32 W) { // TODO: Implement Subtask 1 solution here. // You may leave this function unmodified if you are not attempting this // subtask. i32* const B = new i32[N]; B[0] = 1; std::fill(B + 1, B + N, 0); i32* const R = new i32[N]; playRound(B, R); for (auto i: range(0, N)) { if (R[i] == 0) { return i; } } return 0; } i32 maxValue(const i32 N, const i32 W) { // TODO: Implement Subtask 2 solution here. // You may leave this function unmodified if you are not attempting this // subtask. i32* const B = new i32[N]; i32* const R = new i32[N]; bool* const cand = new bool[N]; std::fill(cand, cand + N, true); i32 size = N; while (size > 1) { for (auto i: range(0, N)) { B[i] = cand[i] ? (W / size) : 0; } playRound(B, R); size = 0; for (auto i: range(0, N)) { cand[i] = (cand[i] && R[i] > B[i]); if (cand[i]) { ++size; } } } for (auto i: range(0, N)) { if (cand[i]) { return i; } } return 0; } i32 greaterValue(const i32 N, const i32 W) { // TODO: Implement Subtask 3 solution here. // You may leave this function unmodified if you are not attempting this // subtask. i32* const B = new i32[N]; i32* const R = new i32[N]; std::fill(B, B + N, 0); auto ask = [&](const i32 num) { B[0] = B[1] = num; playRound(B, R); bool f0 = R[0] > B[0]; bool f1 = R[1] > B[1]; B[0] = B[1] = 0; if (f0 && !f1) return 0; if (!f0 && f1) return 1; if (!f0 && !f1) return 2; if (f0 && f1) return 3; return -1; }; const i32 a = ask(3); if (a == 2) { const i32 b = ask(2); if (b == 2) { return ask(1); } return b; } else if (a == 3) { const i32 b = ask(5); if (b == 3) { return ask(9); } return b; } return a; } template <class Func> void dfs(const i32 l, const i32 r, i32* const A, Func comp) { if (r - l == 1) { return; } const i32 m = (l + r) / 2; dfs(l, m, A, comp); dfs(m, r, A, comp); std::inplace_merge(A + l, A + m, A + r, comp); } void allValues(const i32 N, const i32 W, i32* const P) { i32* const B = new i32[N]; i32* const R = new i32[N]; std::fill(B, B + N, 0); const auto comp = [&](const i32 x, const i32 y) -> bool { if (W == 2 * N) { B[x] = B[y] = W / 2; playRound(B, R); bool res = R[y] > B[y]; B[x] = B[y] = 0; return res; } else { const auto ask = [&](const i32 num) -> int { B[x] = B[y] = num; playRound(B, R); bool f0 = R[x] > B[x]; bool f1 = R[y] > B[y]; B[x] = B[y] = 0; if (f0 && !f1) return 0; if (!f0 && f1) return 1; if (!f0 && !f1) return 2; if (f0 && f1) return 3; return -1; }; const i32 a = ask(3); if (a == 2) { const i32 b = ask(2); if (b == 2) { return ask(1); } return b; } else if (a == 3) { const i32 b = ask(5); if (b == 3) { return ask(9); } return b; } return a; } }; i32* const A = new i32[N]; std::iota(A, A + N, 0); dfs(0, N, A, comp); for (auto i: range(0, N)) { P[A[i]] = i + 1; } } #ifdef LOCAL #include <stdio.h> #include <stdlib.h> static int N, W; static int P[105]; static int maxQueries = 3200; static int numQueries; static void runGame(int F); static void grader(); int main() { grader(); return 0; } void playRound(int *B, int *R) { int i, j; int S = 0; for (i=0;i<N;++i) { if ( !(B[i] >= 0 && B[i] <= W) ) { printf("Invalid query1.\n"); exit(0); } S += B[i]; } if (S > W) { printf("Invalid query2.\n"); exit(0); } numQueries++; if (numQueries > maxQueries) { printf("Too many queries.\n"); exit(0); } int cache[2][205]; int num[2][205]; char taken[105][205]; for (i=0;i<205;++i) { cache[1][i] = 0; num[1][i] = 0; } for (i=0;i<N;++i) { int v = B[i]+1; int ii = i&1; int o = ii^1; for (j=0;j<=W;++j) { cache[ii][j] = cache[o][j]; num[ii][j] = num[o][j]; taken[i][j] = 0; } for (j=W;j>=v;--j) { int h = cache[o][j-v] + P[i]; int hn = num[o][j-v] + 1; if (h > cache[ii][j] || (h == cache[ii][j] && hn > num[ii][j])) { cache[ii][j] = h; num[ii][j] = hn; taken[i][j] = 1; } else { taken[i][j] = 0; } } } int cur = W; for (i=N-1;i>=0;--i) { R[i] = taken[i][cur] ? (B[i] + 1) : 0; cur -= R[i]; } } static void runGame(int F) { int i; scanf("%d %d",&N,&W); for (i=0;i<N;++i) { scanf("%d",&P[i]); } numQueries = 0; if (F == 1) { printf("%d\n", minValue(N, W)); } else if (F == 2) { printf("%d\n", maxValue(N, W)); } else if (F == 3) { printf("%d\n", greaterValue(N, W)); } else if (F == 4) { int userP[105]; allValues(N, W, userP); for (i=0;i<N;i++) { printf("%d ",userP[i]); } printf("\n"); } printf("Made %d calls to playRound.\n", numQueries); } static void grader() { int i; int F, G; scanf("%d %d",&F,&G); for (i=0;i<G;i++) { runGame(F); } } #endif
#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...