結果
| 問題 |
No.1211 円環はお断り
|
| コンテスト | |
| ユーザー |
qwewe
|
| 提出日時 | 2025-05-14 13:25:40 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 5,310 bytes |
| コンパイル時間 | 171 ms |
| コンパイル使用メモリ | 82,976 KB |
| 実行使用メモリ | 262,780 KB |
| 最終ジャッジ日時 | 2025-05-14 13:27:08 |
| 合計ジャッジ時間 | 40,322 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 33 TLE * 8 |
ソースコード
import sys
def solve():
N, K = map(int, sys.stdin.readline().split())
A = list(map(int, sys.stdin.readline().split()))
if N == 0: # Based on constraints 1 <= K <= N, N cannot be 0.
print(0)
return
A_double = A + A
# Max K is N (10^5). log2(10^5) approx 16.6.
# So, we need powers up to 2^16 (dp table rows 0 to 16). Size 17.
# LOG_MAX_K_CONST determines number of rows in dp table.
LOG_MAX_K_CONST = 18 # Sufficient for K up to 2^17-1. Covers K <= 10^5.
# infinity_val indicates a pointer beyond A_double or failure to form segment.
# A_double indices are 0 to 2*N-1.
# next_start[j] can be 2*N if segment A[j...2*N-1] is valid, and next starts "at" 2*N.
# Or 2*N if no segment can be formed.
infinity_val = 2 * N
# memo_can_check = {} # Optional: memoization for can() if N is small, but not needed here.
def can(m_test):
# if m_test in memo_can_check: return memo_can_check[m_test]
# 1. Calculate next_start array using two pointers.
# next_s[j] = p, where segment A_double[j...p-1] has sum >= m_test, and p is smallest such.
# p is the exclusive end index (start of the next segment).
# If no such segment, p = infinity_val.
next_s = [infinity_val] * (2 * N)
current_sum = 0
right_ptr = 0 # Exclusive end of the current window [left_ptr, right_ptr)
for left_ptr in range(2 * N):
# Expand window to the right until sum >= m_test or end of A_double
while right_ptr < 2 * N and current_sum < m_test:
current_sum += A_double[right_ptr]
right_ptr += 1
if current_sum >= m_test:
next_s[left_ptr] = right_ptr
# else: next_s[left_ptr] remains infinity_val (initialized)
# Shrink window from the left for the next iteration
# current_sum is for window [left_ptr, right_ptr)
# For next iteration (left_ptr+1), sum will be for [left_ptr+1, right_ptr)
current_sum -= A_double[left_ptr]
# If A_double[left_ptr] was very large, current_sum could become negative.
# However, A_i >= 1, so this won't make sum negative unless m_test itself is strange.
# No need for `if current_sum < 0: current_sum = 0` if A_i positive.
# 2. Build DP table for jumps (binary lifting)
# dp[k][i] = end position (start of next segment) after 2^k segments, starting from i.
# dp table dimensions: LOG_MAX_K_CONST rows, 2*N + 1 columns (for index 2*N = infinity_val)
dp = [[infinity_val] * (2 * N + 1) for _ in range(LOG_MAX_K_CONST)]
# Base case: dp[0][i] is one jump
for i in range(2 * N):
dp[0][i] = next_s[i]
dp[0][infinity_val] = infinity_val # dp[0][2*N] = 2*N, ensures infinity propagates
# Fill DP table
for k_power in range(1, LOG_MAX_K_CONST):
for i in range(2 * N + 1): # Iterate up to 2*N (infinity_val index)
intermediate_pos = dp[k_power-1][i]
# intermediate_pos will be an index from 0 to 2*N.
# dp[k_power-1] is defined for all these indices.
dp[k_power][i] = dp[k_power-1][intermediate_pos]
# 3. Check for each starting position s in the original circle
for s_original_idx in range(N): # s_original_idx is the start in A_double as well
current_pos = s_original_idx
# Perform K jumps using the DP table
temp_K = K
for k_bit_idx in range(LOG_MAX_K_CONST):
if (temp_K >> k_bit_idx) & 1: # If 2^(k_bit_idx) is part of K
current_pos = dp[k_bit_idx][current_pos]
# If current_pos becomes infinity_val, it will stay infinity_val
# due to dp[...][infinity_val] = infinity_val.
# After K jumps, current_pos is the start of the (K+1)-th segment.
# The K segments are A_double[s_original_idx ... current_pos-1].
# Total number of beads used = current_pos - s_original_idx.
# We need this to be at most N.
# This condition also implicitly checks if current_pos < infinity_val,
# because if current_pos = infinity_val (2*N), then 2*N - s_original_idx <= N
# implies N <= s_original_idx, which is false since s_original_idx < N.
if (current_pos - s_original_idx) <= N:
# memo_can_check[m_test] = True
return True
# memo_can_check[m_test] = False
return False
# Binary search for M
low = 1
# Max possible M is sum of all A's (for K=1). Max sum A_i = 10^9, N=10^5 => sum ~ 10^14.
high = 0
for x_val in A: high += x_val
ans = 0 # Stores the maximum M found so far.
while low <= high:
mid = low + (high - low) // 2
if mid == 0: # Should not happen as low starts at 1 and A_i >= 1 (so high >= 1)
low = 1
continue
if can(mid):
ans = mid
low = mid + 1 # Try for a larger M
else:
high = mid - 1 # M is too large
sys.stdout.write(str(ans) + "\n")
solve()
qwewe