Submission #441785

#TimeUsernameProblemLanguageResultExecution timeMemory
441785fleimgruberDungeons Game (IOI21_dungeons)C++17
37 / 100
576 ms254660 KiB
#include "dungeons.h"
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 400001;
const int MAX_LOG = 25; // 2^24 > 10^7

int n, p[MAX_N], l[MAX_N];
struct {
	int end;
	long long gained;
	long long min; // min(sum(gained) - opponent)
} dp[MAX_N][MAX_LOG];

void init(int n_, vector<int> s, vector<int> p_,
		vector<int> w, vector<int> l_) {
	n = n_;
	copy_n(p_.begin(), n, p);
	copy_n(l_.begin(), n, l);
	l[n] = n;
	for (int j = 0; j < MAX_LOG; j++)
		for (int i = 0; i <= n; i++) {
			auto& x = dp[i][j];
			if (j == 0)
				if (i == n) {
					x.end = n;
					x.gained = x.min = 0;
				} else {
					x.end = w[i];
					x.gained = s[i];
					x.min = -s[i];
				}
			else {
				auto& a = dp[i][j - 1];
				auto& b = dp[a.end][j - 1];
				x.end = b.end;
				x.gained = a.gained + b.gained;
				x.min = min(a.min, a.gained + b.min);
			}
		}
}

// because p[i] = s[i], every time we lose, our strength doubles
// => we only lose log(max(s)) times. use binary lifting to find next
//	  fight we lose
long long simulate(int at, int strength) {
	// do we lose any of the next 2^j fights?
	auto lose = [&](int j) {
		return strength + dp[at][j].min < 0;
	};
	while (at != n) {
		// jump until we lose
		for (int j = MAX_LOG - 1; j >= 0; j--)
			if (!lose(j)) {
				auto& x = dp[at][j];
				at = x.end;
				strength += x.gained;
			}
		// lose (if at = n, this adds 0)
		strength += p[at]; // = s[at] > strength
		at = l[at];
	}
	return strength;
}
#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...