結果
| 問題 | No.3588 Already Ready |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-05-28 13:21:32 |
| 言語 | PyPy3 (7.3.17) |
| 結果 |
AC
|
| 実行時間 | 1,524 ms / 3,000 ms |
| コード長 | 5,515 bytes |
| 記録 | |
| コンパイル時間 | 231 ms |
| コンパイル使用メモリ | 95,912 KB |
| 実行使用メモリ | 148,832 KB |
| 最終ジャッジ日時 | 2026-07-10 20:54:26 |
| 合計ジャッジ時間 | 13,523 ms |
|
ジャッジサーバーID (参考情報) |
judge3_0 / judge2_1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 69 |
ソースコード
import sys
# 再帰上限の引き上げ(セグメント木用)
sys.setrecursionlimit(2000000)
def solve():
input_data = sys.stdin.read().split()
if not input_data:
return
N = int(input_data[0])
K = int(input_data[1])
M = int(input_data[2])
A = [int(x) for x in input_data[3:3+N]]
total_A = sum(A)
if total_A % (N + 1) != 0:
print(-1)
return
T = total_A // (N + 1)
if T == 0:
print(-1)
return
W = [0] * (N + 1)
for i in range(1, N + 1):
W[i] = A[i-1] - T
if W[i] < 0:
print(-1)
return
if W[M] == 0 or A[M-1] < K + 2:
print(-1)
return
C = [0] * (N + 1)
U = [0] * (N + 1)
for i in range(1, N + 1):
if i != M:
C[i] = W[i]
U[i] = K - W[i]
else:
C[i] = W[i] - 1
U[i] = K - W[i] + 1
if C[i] > 0 and U[i] < 0:
print(-1)
return
U[i] = min(U[i], T - 2)
if T == 1:
# T=1 の場合、上記の A[M-1] < K + 2 の判定で既にはじかれているはずですが念のため
print(-1)
return
MAX_T = T - 1
count_U = [0] * MAX_T
for i in range(1, N + 1):
if C[i] > 0:
count_U[U[i]] += C[i]
S = [0] * MAX_T
curr_S = 0
for x in range(MAX_T):
curr_S += count_U[x]
S[x] = curr_S
V = [0] * MAX_T
for x in range(MAX_T):
V[x] = x - S[x]
if V[x] < -1:
print(-1)
return
# V用 セグメント木の配列と関数
v_tree = [0] * (4 * MAX_T)
v_lazy = [0] * (4 * MAX_T)
def build_v(node, start, end):
if start == end:
v_tree[node] = V[start]
return
mid = (start + end) // 2
build_v(2 * node, start, mid)
build_v(2 * node + 1, mid + 1, end)
v_tree[node] = min(v_tree[2 * node], v_tree[2 * node + 1])
def add_v(node, start, end, l, r, val):
if r < start or end < l:
return
if l <= start and end <= r:
v_tree[node] += val
v_lazy[node] += val
return
lz = v_lazy[node]
if lz != 0:
v_tree[2 * node] += lz
v_lazy[2 * node] += lz
v_tree[2 * node + 1] += lz
v_lazy[2 * node + 1] += lz
v_lazy[node] = 0
mid = (start + end) // 2
add_v(2 * node, start, mid, l, r, val)
add_v(2 * node + 1, mid + 1, end, l, r, val)
v_tree[node] = min(v_tree[2 * node], v_tree[2 * node + 1])
def find_first_v(node, start, end, t, target):
if v_tree[node] > target or end < t:
return -1
if start == end:
return start
lz = v_lazy[node]
if lz != 0:
v_tree[2 * node] += lz
v_lazy[2 * node] += lz
v_tree[2 * node + 1] += lz
v_lazy[2 * node + 1] += lz
v_lazy[node] = 0
mid = (start + end) // 2
res = find_first_v(2 * node, start, mid, t, target)
if res != -1:
return res
return find_first_v(2 * node + 1, mid + 1, end, t, target)
# チーム探索用 セグメント木の配列と関数
MAX_N = N
INF = 10**9
team_tree = [INF] * (4 * (MAX_N + 1))
def build_team(node, start, end):
if start == end:
team_tree[node] = U[start] if C[start] > 0 else INF
return
mid = (start + end) // 2
build_team(2 * node, start, mid)
build_team(2 * node + 1, mid + 1, end)
team_tree[node] = min(team_tree[2 * node], team_tree[2 * node + 1])
def update_team(node, start, end, idx, val):
if start == end:
team_tree[node] = val
return
mid = (start + end) // 2
if idx <= mid:
update_team(2 * node, start, mid, idx, val)
else:
update_team(2 * node + 1, mid + 1, end, idx, val)
team_tree[node] = min(team_tree[2 * node], team_tree[2 * node + 1])
def find_first_team(node, start, end, X):
if team_tree[node] > X:
return -1
if start == end:
return start
mid = (start + end) // 2
res = find_first_team(2 * node, start, mid, X)
if res != -1:
return res
return find_first_team(2 * node + 1, mid + 1, end, X)
# 初期化
build_v(1, 0, MAX_T - 1)
build_team(1, 0, MAX_N)
ans = []
# 各試合(最後の試合を除く)の勝者を貪欲に決定
for t in range(MAX_T):
X = find_first_v(1, 0, MAX_T - 1, t, t - 1)
if X == -1:
print(-1)
return
best_team = find_first_team(1, 0, MAX_N, X)
if best_team == -1:
print(-1)
return
ans.append(best_team)
C[best_team] -= 1
# 必要な勝利数を満たしたチームは除外
if C[best_team] == 0:
update_team(1, 0, MAX_N, best_team, INF)
# V配列の更新(使ったチームのデッドライン以降の余裕度が回復する)
add_v(1, 0, MAX_T - 1, U[best_team], MAX_T - 1, 1)
# 最後の試合は必ずMが勝利する
ans.append(M)
print(T)
print(" ".join(map(str, ans)))
if __name__ == '__main__':
solve()