Submission #924879

#TimeUsernameProblemLanguageResultExecution timeMemory
924879Programmer123Dungeons Game (IOI21_dungeons)C++17
36 / 100
7131 ms1480492 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; int *ffl, *ffw; __int128_t *sffl, *sffw; long long dp(int node, long long str); long long calc(int node, long long str) { if (str >= s[node]) { return dp(ffw[node], str + sffw[node]); } else return dp(ffl[node], str + sffl[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]; ffl = new int[N + 1]; ffw = new int[N + 1]; sffl = new __int128_t[N + 1]; sffw = new __int128_t[N + 1]; for (int i = 0; i <= N; ++i) { gainBlitz[i] = -1; ffl[i] = -1; ffw[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]; }; std::function<void(int)> calcw = [&](int x) { if (ffw[x] != -1) return; if (x == N) { ffw[x] = N; sffw[x] = 0; return; } calcw(w[x]); if (w[x] != N && 2 * s[x] >= s[w[x]]) { ffw[x] = ffw[w[x]]; sffw[x] = s[x] + sffw[w[x]]; } else { ffw[x] = w[x]; sffw[x] = s[x]; } }; std::function<void(int)> calcl = [&](int x) { if (ffl[x] != -1) return; ffl[x] = l[x]; sffl[x] = p[x]; if (x == N) { ffl[x] = N; sffl[x] = 0; return; } calcl(l[x]); if (l[x] != N && p[x] + s[x] <= s[l[x]]) { ffl[x] = ffl[l[x]]; sffl[x] = p[x] + sffl[l[x]]; } else { ffl[x] = l[x]; sffl[x] = p[x]; } }; for (int i = 0; i <= N; ++i) { calc(i); calcl(i); calcw(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:144:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  144 |         for (int i = 0; i < sValues.size(); ++i) {
      |                         ~~^~~~~~~~~~~~~~~~
dungeons.cpp: In function 'long long int simulate(int, int)':
dungeons.cpp:193:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  193 |         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...