結果
問題 |
No.2554 MMA文字列2 (Query Version)
|
ユーザー |
|
提出日時 | 2025-05-03 00:59:19 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 1,268 ms / 5,000 ms |
コード長 | 3,800 bytes |
コンパイル時間 | 471 ms |
コンパイル使用メモリ | 82,176 KB |
実行使用メモリ | 186,672 KB |
最終ジャッジ日時 | 2025-05-03 01:00:21 |
合計ジャッジ時間 | 52,549 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 55 |
ソースコード
## https://yukicoder.me/problems/no/2554 from collections import deque ARRAY_SIZE = 26 * 3 + 1 class SegmentTree: """ 非再帰版セグメント木。 更新は「加法」、取得は「最大値」のもの限定。 """ def __init__(self, init_array): n = 1 while n < len(init_array): n *= 2 self.size = n self.array = [ [0] * ARRAY_SIZE for _ in range(2 * self.size)] self.weights = [0 for _ in range(2 * self.size)] for i, a in enumerate(init_array): o = ord(a) - ord("A") self.array[self.size + i][o] = 1 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.weights[i] = self.weights[2 * i] + self.weights[2 * i + 1] self._op(self.array[i], self.array[2 * i], self.array[2 * i + 1], self.weights[2 * i + 1]) end_index = start_index start_index = end_index // 2 def _op(self, array, left, right, right_weight): # 1文字のアルファベット for j in range(26): array[j] = left[j] + right[j] # 同じ文字が2回連続続くもの for j in range(26): array[j + 26] = left[j + 26] + right[j + 26] for j in range(26): array[j + 26] += left[j] * right[j] # 2種類の文字 for j in range(26): array[j + 52] = left[j + 52] + right[j + 52] for j in range(26): array[j + 52] += left[j] * (right_weight - right[j]) # MMA文字 array[78] = left[78] + right[78] for j in range(26): array[78] += left[j + 26] * (right_weight - right[j]) array[78] += left[j] * right[j + 52] def set(self, x, a, old_a): index = self.size + x o = ord(a) - ord("A") old_o = ord(old_a) - ord("A") self.array[index][old_o] = 0 self.array[index][o] = 1 while index > 1: index //= 2 self._op(self.array[index], self.array[2 * index], self.array[2 * index + 1], self.weights[2 * index + 1]) def get_value(self, l, r): L = self.size + l; R = self.size + r # 2. 区間[l, r)の最大値を求める rignt_queue = deque() left_queue = deque() while L < R: if R & 1: R -= 1 rignt_queue.appendleft(R) if L & 1: left_queue.append(L) L += 1 L >>= 1; R >>= 1 s = [0] * ARRAY_SIZE while len(left_queue) > 0: index = left_queue.popleft() new_s = [0] * ARRAY_SIZE self._op(new_s, s, self.array[index], self.weights[index]) s = new_s while len(rignt_queue) > 0: index = rignt_queue.popleft() new_s = [0] * ARRAY_SIZE self._op(new_s, s, self.array[index], self.weights[index]) s = new_s return s def main(): N = int(input()) S = input() Q = int(input()) queries = [] for _ in range(Q): values = input().split() queries.append(values) seg_tree = SegmentTree(S) s_array = [s for s in S] for values in queries: if values[0] == "1": _, x, c = values x = int(x) - 1 old_c = s_array[x] seg_tree.set(x, c, old_c) s_array[x] = c else: _, l, r = values l = int(l) - 1 r = int(r) - 1 v_list = seg_tree.get_value(l, r + 1) print(v_list[-1]) if __name__ == "__main__": main()