제출 #991212

#제출 시각아이디문제언어결과실행 시간메모리
991212model_codeMarathon Race 2 (JOI24_ho_t3)C++17
100 / 100
190 ms33780 KiB
/*
	FULL-SCORE SOLUTION
	- Time Complexity: O((N + Q) * log N + maxT)
*/

#include <bits/stdc++.h>
using namespace std;

// limits the problem to "the first ball to take is the leftmost"
vector<bool> solve_oneside(int N, int L, vector<int> X, vector<int> W, int Q, vector<int> S, vector<int> G, vector<int> T) {
	// step #1. preparation
	const long long INF = 3LL << 59;
	vector<int> SW(N + 1);
	for (int i = 0; i < N; i++) {
		SW[i + 1] = SW[i] + W[i];
	}
	auto chmin = [&](long long& a, long long b) -> void {
		a = min(a, b);
	};

	// step #2. dynamic programming
	// - dp[l][r][d]: minimum time when "took balls at X[0], ..., X[l] and X[r], ..., X[N-1] and the current position is X[l] (d=0) or X[r] (d=1)"
	vector<vector<array<long long, 2> > > dp(N + 1, vector<array<long long, 2> >(N + 1, {INF, INF}));
	dp[0][N][0] = W[0];
	for (int l = 0; l <= N; l++) {
		for (int r = N; r >= l + 2; r--) {
			int balls = SW[l + 1] + (SW[N] - SW[r]); // number of carrying balls
			chmin(dp[l + 1][r][0], dp[l][r][0] + (long long)(X[l + 1] - X[l]) * (balls + 1) + W[l + 1]); // X[l] -> X[l+1]
			chmin(dp[l][r - 1][1], dp[l][r][0] + (long long)(X[r - 1] - X[l]) * (balls + 1) + W[r - 1]); // X[l] -> X[r-1]
			if (r != N) {
				chmin(dp[l + 1][r][0], dp[l][r][1] + (long long)(X[r] - X[l + 1]) * (balls + 1) + W[l + 1]); // X[r] -> X[l+1]
				chmin(dp[l][r - 1][1], dp[l][r][1] + (long long)(X[r] - X[r - 1]) * (balls + 1) + W[r - 1]); // X[r] -> X[r-1]
			}
		}
	}

	// step #3. calculate answer
	vector<bool> ans(Q, false);
	for (int i = 0; i < Q; i++) {
		int pos = lower_bound(X.begin(), X.end(), G[i] + 1) - X.begin();
		if (pos != 0) {
			long long mintime = INF;
			chmin(mintime, dp[pos - 1][pos][0] + abs(S[i] - X[0]) + (long long)(G[i] - X[pos - 1]) * (SW[N] + 1)); // S[i] -> X[0] -> ... -> X[pos-1] -> G[i]
			chmin(mintime, dp[pos - 1][pos][1] + abs(S[i] - X[0]) + (long long)(X[pos] - G[i]) * (SW[N] + 1)); // S[i] -> X[0] -> ... -> X[pos] -> G[i]
			ans[i] = (mintime <= T[i]);
		}
	}

	return ans;
}

// solve function
vector<bool> solve(int N, int L, vector<int> X, int Q, vector<int> S, vector<int> G, vector<int> T) {
	// step #1. compression
	vector<int> SX = X;
	sort(SX.begin(), SX.end());
	vector<int> CX = SX;
	CX.erase(unique(CX.begin(), CX.end()), CX.end());
	int CN = CX.size();
	int cur = 0;
	vector<int> W(CN);
	for (int i = 0; i < CN; i++) {
		while (cur != N && SX[cur] == CX[i]) {
			W[i] += 1;
			cur += 1;
		}
	}

	// step #2. consider limit (1+2+3+4+...)
	int maxT = *max_element(T.begin(), T.end());
	if ((long long)(CN) * (CN + 1) / 2 > maxT) {
		return vector<bool>(Q, false);
	}
	
	// step #3. consider two directions
	vector<bool> ans(Q, false);
	for (int i = 0; i < 2; i++) {
		// get answer
		vector<bool> res = solve_oneside(CN, L, CX, W, Q, S, G, T);
		for (int j = 0; j < Q; j++) {
			ans[j] = ans[j] || res[j];
		}
		// reverse
		for (int j = 0; j < CN; j++) {
			CX[j] = L - CX[j];
		}
		reverse(CX.begin(), CX.end());
		reverse(W.begin(), W.end());
		for (int j = 0; j < Q; j++) {
			S[j] = L - S[j];
			G[j] = L - G[j];
		}
	}

	return ans;
}

int main() {
	// input
	cin.tie(0);
	ios::sync_with_stdio(false);
	int N, L;
	cin >> N >> L;
	vector<int> X(N);
	for (int i = 0; i < N; i++) {
		cin >> X[i];
	}
	int Q;
	cin >> Q;
	vector<int> S(Q), G(Q), T(Q);
	for (int i = 0; i < Q; i++) {
		cin >> S[i] >> G[i] >> T[i];
	}

	// output
	vector<bool> ans = solve(N, L, X, Q, S, G, T);
	for (int i = 0; i < Q; i++) {
		cout << (ans[i] ? "Yes\n" : "No\n");
	}

	return 0;
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...