結果
| 問題 |
No.878 Range High-Element Query
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-08-18 21:58:48 |
| 言語 | PyPy3 (7.3.15) |
| 結果 |
AC
|
| 実行時間 | 334 ms / 2,000 ms |
| コード長 | 2,787 bytes |
| コンパイル時間 | 361 ms |
| コンパイル使用メモリ | 82,452 KB |
| 実行使用メモリ | 101,460 KB |
| 最終ジャッジ日時 | 2024-08-18 21:58:54 |
| 合計ジャッジ時間 | 4,764 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 18 |
ソースコード
# https://yukicoder.me/problems/no/878
import math
from collections import deque
MAX_INT = 10 ** 18
class SegmentTree:
"""
非再帰版セグメント木。
更新は「加法」、取得は「最大値」のもの限定。
"""
def __init__(self, init_array):
n = 1
while n < len(init_array):
n *= 2
self.size = n
self.array = [MAX_INT] * (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] = min(self.array[2 * i], self.array[2 * i + 1])
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] = min(self.array[2 * index], self.array[2 * index + 1])
def get_min(self, l, r):
L = self.size + l; R = self.size + r
# 2. 区間[l, r)の最大値を求める
s = MAX_INT
while L < R:
if R & 1:
R -= 1
s = min(s, self.array[R])
if L & 1:
s = min(s, self.array[L])
L += 1
L >>= 1; R >>= 1
return s
def main():
N, Q = map(int, input().split())
A = list(map(int, input().split()))
queries = []
for _ in range(Q):
_, l, r = map(int, input().split())
queries.append((l - 1, r - 1))
# 各aについて次に大きくなるiを求める
seg_tree = SegmentTree([MAX_INT] * (N + 1))
min_right_index = [-1] * N
for i in reversed(range(N)):
a = A[i]
ans = seg_tree.get_min(a + 1, N + 1)
min_right_index[i] = ans
seg_tree.set(a, i)
# ダブリングで2^k先の大きくなるポイントへの移動を求める
k = 1
while (1 << k) < N:
k += 1
max_k = k + 1
min_right_index_list = [[MAX_INT] * N for _ in range(max_k + 1)]
min_right_index_list[0] = min_right_index
for k in range(1, max_k + 1):
for i in range(N):
n = min_right_index_list[k - 1][i]
if n < MAX_INT:
min_right_index_list[k][i] = min_right_index_list[k - 1][n]
for l, r in queries:
answer = 1
for k in reversed(range(max_k + 1)):
if min_right_index_list[k][l] < MAX_INT:
n = min_right_index_list[k][l]
if n <= r:
l = n
answer += 1 << k
print(answer)
if __name__ == "__main__":
main()