Submission #924878

#TimeUsernameProblemLanguageResultExecution timeMemory
924878Programmer123Dungeons Game (IOI21_dungeons)C++17
36 / 100
7158 ms1668020 KiB
#include "dungeons.h" #include <bits/stdc++.h> #define JUMP_SIZE 40 std::vector<int> s, p, w, l; int N; long long *minBlitz, *gainBlitz; int **jumpTo; __int128_t **jumpGain; bool identical = true; std::vector<int> sValues; std::vector<std::pair<int **, __int128_t **>> jumps; long long dp(int node, long long str); long long calc(int node, long long str) { if (str >= s[node]) { return dp(w[node], str + s[node]); } else return dp(l[node], str + p[node]); } std::unordered_map<long long, long long> *cache; long long dp(int node, long long str) { assert(node != N); if (str >= minBlitz[node]) return str + gainBlitz[node]; if (!cache[node].count(str)) { cache[node][str] = calc(node, str); } return cache[node][str]; } void init(int n, std::vector<int> _s, std::vector<int> _p, std::vector<int> _w, std::vector<int> _l) { N = n; s = std::move(_s); p = std::move(_p); w = std::move(_w); l = std::move(_l); for (int i = 1; i < N; ++i) { if (s[i] != s[0]) identical = false; } minBlitz = new long long[N + 1]; gainBlitz = new long long[N + 1]; for (int i = 0; i <= N; ++i) { gainBlitz[i] = -1; } std::function<void(int)> calc = [&](int x) { if (gainBlitz[x] != -1) return; if (x == N) { minBlitz[x] = 0; gainBlitz[x] = 0; return; } calc(w[x]); minBlitz[x] = std::max(minBlitz[w[x]] - s[x], (long long) s[x]); gainBlitz[x] = gainBlitz[w[x]] + s[x]; }; for (int i = 0; i <= N; ++i) { calc(i); } cache = new std::remove_pointer<decltype(cache)>::type[N + 1]; #ifdef LOCAL std::cout << "minBlitz:"; for (int i = 0; i <= N; ++i) { std::cout << " " << minBlitz[i]; } std::cout << std::endl; std::cout << "gainBlitz:"; for (int i = 0; i <= N; ++i) { std::cout << " " << gainBlitz[i]; } std::cout << std::endl; #endif jumpTo = new int *[N + 1]; jumpGain = new __int128_t *[N + 1]; for (int i = 0; i <= N; ++i) { jumpTo[i] = new int[JUMP_SIZE]; jumpGain[i] = new __int128_t[JUMP_SIZE]; } for (int i = 0; i < N; ++i) { jumpTo[i][0] = l[i]; jumpGain[i][0] = p[i]; } jumpTo[N][0] = N; jumpGain[N][0] = 0; for (int i = 1; i < JUMP_SIZE; ++i) { for (int j = 0; j <= N; ++j) { jumpTo[j][i] = jumpTo[jumpTo[j][i - 1]][i - 1]; jumpGain[j][i] = jumpGain[j][i - 1] + jumpGain[jumpTo[j][i - 1]][i - 1]; } } std::set<int> svalues; for (int i = 0; i < N; ++i) { svalues.insert(s[i]); } for (auto x: svalues) { sValues.push_back(x); } if (sValues.size() <= 5) { for (int i = 0; i < sValues.size(); ++i) { auto to = new int *[N + 1]; auto gain = new __int128_t *[N + 1]; jumps.emplace_back(to, gain); for (int j = 0; j <= N; ++j) { to[j] = new int[JUMP_SIZE]; gain[j] = new __int128_t[JUMP_SIZE]; } int prev = 0; if (i) prev = sValues[i - 1]; for (int j = 0; j < N; ++j) { if (s[j] > prev) { to[j][0] = l[j]; gain[j][0] = p[j]; } else { to[j][0] = w[j]; gain[j][0] = s[j]; } } to[N][0] = N; gain[N][0] = 0; for (int k = 1; k < JUMP_SIZE; ++k) { for (int j = 0; j <= N; ++j) { to[j][k] = to[to[j][k - 1]][k - 1]; gain[j][k] = gain[j][k - 1] + gain[to[j][k - 1]][k - 1]; } } } } } long long simulate(int x, int _z) { __int128_t z = _z; if (identical) { if (z >= s[0]) return z + gainBlitz[x]; for (int i = JUMP_SIZE - 1; i >= 0; --i) { if (z + jumpGain[x][i] <= s[0]) { z += jumpGain[x][i]; x = jumpTo[x][i]; } } while (z < s[0]) { if (x == N) return z; z += p[x]; x = l[x]; } return z + gainBlitz[x]; } if (sValues.size() <= 5) { for (int _ = 0; _ < sValues.size(); ++_) { if (z < sValues[_]) { auto [to, gain] = jumps[_]; for (int i = JUMP_SIZE - 1; i >= 0; --i) { if (z + gain[x][i] <= sValues[_]) { z += gain[x][i]; x = to[x][i]; } } while (z < sValues[_]) { if (x == N) return z; if (z >= s[x]) { z += s[x]; x = w[x]; } else { z += p[x]; x = l[x]; } } } } return z + gainBlitz[x]; } return dp(x, z); }

Compilation message (stderr)

dungeons.cpp: In function 'void init(int, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>)':
dungeons.cpp:100:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  100 |         for (int i = 0; i < sValues.size(); ++i) {
      |                         ~~^~~~~~~~~~~~~~~~
dungeons.cpp: In function 'long long int simulate(int, int)':
dungeons.cpp:149:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  149 |         for (int _ = 0; _ < sValues.size(); ++_) {
      |                         ~~^~~~~~~~~~~~~~~~
#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...