結果
問題 |
No.2571 列辞書順列
|
ユーザー |
|
提出日時 | 2025-07-13 18:16:53 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 586 ms / 3,000 ms |
コード長 | 5,137 bytes |
コンパイル時間 | 389 ms |
コンパイル使用メモリ | 82,352 KB |
実行使用メモリ | 102,224 KB |
最終ジャッジ日時 | 2025-07-13 18:17:12 |
合計ジャッジ時間 | 17,906 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 29 |
ソースコード
## https://yukicoder.me/problems/no/2040 from collections import deque MOD = 998244353 class SegmentTree: """ 非再帰版セグメント木。 更新は「加法」、取得は「最大値」のもの限定。 """ def __init__(self, init_array): n = 1 while n < len(init_array): n *= 2 self.size = n self.array = [0] * (2 * self.size) for i, a in enumerate(init_array): self.array[self.size + i] = a end_index = self.size start_index = end_index // 2 while start_index >= 1: for i in range(start_index, end_index): self.array[i] = (self.array[2 * i] + self.array[2 * i + 1]) % MOD end_index = start_index start_index = end_index // 2 def set(self, x, a): index = self.size + x self.array[index] = a while index > 1: index //= 2 self.array[index] = (self.array[2 * index] + self.array[2 * index + 1]) % MOD def get_sum(self, l, r): L = self.size + l; R = self.size + r # 2. 区間[l, r)の最大値を求める s = 0 while L < R: if R & 1: R -= 1 s += self.array[R] s %= MOD if L & 1: s += self.array[L] s %= MOD L += 1 L >>= 1; R >>= 1 return s class SegmentTreeCoef: """ 非再帰版セグメント木。 更新は「加法」、取得は「最大値」のもの限定。 """ def __init__(self, init_array, M): n = 1 while n < len(init_array): n *= 2 self.m_array = [0] * (len(init_array) + 1) m = 1 for i in range(len(init_array) + 1): self.m_array[i] = m m *= M m %= MOD self.size = n self.array = [0] * (2 * self.size) self.weights = [0] * (2 * self.size) for i, a in enumerate(init_array): self.array[self.size + i] = a self.weights[self.size + i] = 1 end_index = self.size start_index = end_index // 2 while start_index >= 1: for i in range(start_index, end_index): self.array[i] = self._op(self.array[2 * i], self.array[2 * i + 1], self.weights[2 * i + 1]) self.weights[i] = (self.weights[2 * i] + self.weights[2 * i + 1]) end_index = start_index start_index = end_index // 2 def _op(self, left, right, right_weight): x = (left * self.m_array[right_weight]) % MOD x += right x %= MOD return x def set(self, x, a): index = self.size + x self.array[index] = a while index > 1: index //= 2 self.array[index] = self._op(self.array[2 * index], self.array[2 * index + 1], self.weights[2 * index + 1]) def get_sum(self, l, r): L = self.size + l; R = self.size + r left_queue = deque() right_queue = deque() # 2. 区間[l, r)の最大値を求める s = 0 while L < R: if R & 1: R -= 1 right_queue.appendleft(R) if L & 1: left_queue.append(L) L += 1 L >>= 1; R >>= 1 while len(left_queue) > 0: x = left_queue.popleft() s = self._op(s, self.array[x], self.weights[x]) while len(right_queue) > 0: x = right_queue.popleft() s = self._op(s, self.array[x], self.weights[x]) return s def solve_case_m1(N, K, Q, A, queries): for values in queries: if values[0] == 1: _, l, r = values l -= 1 r -= 1 length = r - l + 1 print(length) def solve_case_many_m(N, M, K, Q, A, queries): seg_tree_const = SegmentTree([a - 1 for a in A]) seg_tree_coef = SegmentTreeCoef([a - 1 for a in A], M) inv_m0 = pow(M - 1, MOD - 2, MOD) for values in queries: if values[0] == 1: _, l, r = values l -= 1 r -= 1 coef = seg_tree_coef.get_sum(l, r + 1) x = r - l x = K - x m0 = pow(M, x, MOD) c = (coef * m0) % MOD const = seg_tree_const.get_sum(l, r + 1) c -= const c %= MOD c *= inv_m0 c %= MOD c += (r - l) c %= MOD print((c + 1) % MOD) else: _, x, y = values x -= 1 seg_tree_coef.set(x, y - 1) seg_tree_const.set(x, y - 1) def main(): N, M, K, Q = map(int, input().split()) A = list(map(int, input().split())) queries = [] for _ in range(Q): values = tuple(map(int, input().split())) queries.append(values) if M == 1: solve_case_m1(N, K, Q, A, queries) else: solve_case_many_m(N, M, K, Q, A, queries) if __name__ == "__main__": main()