結果
| 問題 |
No.1778 括弧列クエリ / Bracketed Sequence Query
|
| コンテスト | |
| ユーザー |
norioc
|
| 提出日時 | 2025-03-26 00:14:13 |
| 言語 | Python3 (3.13.1 + numpy 2.2.1 + scipy 1.14.1) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 4,194 bytes |
| コンパイル時間 | 640 ms |
| コンパイル使用メモリ | 12,928 KB |
| 実行使用メモリ | 91,352 KB |
| 最終ジャッジ日時 | 2025-03-26 00:14:32 |
| 合計ジャッジ時間 | 18,753 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | -- * 1 |
| other | AC * 8 TLE * 1 -- * 18 |
ソースコード
from collections import defaultdict
from itertools import count
import sys
sys.setrecursionlimit(10 ** 6)
#input = sys.stdin.readline
try:
import pypyjit
pypyjit.set_param('max_unroll_recursion=-1')
except ModuleNotFoundError:
pass
class LCA:
def __init__(self, n, adj, root=0):
K = 1
while (1 << K) < n: K += 1
parent = [[-1] * n for _ in range(K)]
dist = [-1] * n
def dfs():
s = [(root, -1, 0)]
while s:
v, par, depth = s.pop()
parent[0][v] = par
dist[v] = depth
for to in adj[v]:
if to == par: continue
s.append((to, v, depth+1))
dfs()
for k in range(K-1):
for v in range(n):
if parent[k][v] < 0: continue
parent[k+1][v] = parent[k][parent[k][v]]
self.parent = parent
self.dist = dist
def query(self, u, v) -> int:
"""二頂点 u, v の LCA"""
if self.dist[u] < self.dist[v]: u, v = v, u
K = len(self.parent)
# LCA までの距離を同じにする
for k in range(K):
if (self.dist[u] - self.dist[v]) >> k & 1:
u = self.parent[k][u]
# 二分探索で LCA を求める
if u == v: return u
for k in range(K-1, -1, -1):
if self.parent[k][u] != self.parent[k][v]:
u = self.parent[k][u]
v = self.parent[k][v]
return self.parent[0][u]
def distance(self, u, v) -> int:
"""二頂点 u, v の距離"""
return self.dist[u] + self.dist[v] - 2 * self.dist[self.query(u, v)]
def is_on_path(self, u, v, a) -> bool:
"""二頂点 u, v 上に a があるか"""
return self.distance(u, a) + self.distance(a, v) == self.distance(u, v)
class Reader:
def __init__(self, data: list):
self.data = data
self.p = 0
def has_next(self) -> bool:
return self.p < len(self.data)
def peek(self):
assert self.has_next()
return self.data[self.p]
def next_indexed(self):
assert self.has_next()
v = self.data[self.p]
p = self.p
self.p += 1
return v, p
def next(self):
assert self.has_next()
v = self.data[self.p]
self.p += 1
return v
class Node:
def __init__(self, left, right, children):
self.left = left # 開き括弧のインデックス
self.right = right # 閉じ括弧のインデックス
self.children = children
def tree_size(self) -> int:
res = 1
for child in self.children:
res += child.tree_size()
return res
def make_tree(reader: Reader) -> Node:
assert reader.peek() == '('
v, l = reader.next_indexed()
children = []
while reader.has_next():
match reader.peek():
case ')':
_, r = reader.next_indexed()
return Node(l, r, children)
case '(':
c = make_tree(reader)
children.append(c)
assert False
def traverse(node: Node):
def dfs(node, node_id, adj, ind2id, id2node, counter):
id2node[node_id] = node
ind2id[node.left] = node_id
ind2id[node.right] = node_id
for child in node.children:
id = next(counter)
adj[node_id].append(id)
adj[id].append(node_id)
dfs(child, id, adj, ind2id, id2node, counter)
counter = count()
root_id = next(counter)
adj = defaultdict(list)
ind2id = {}
id2node = {}
dfs(node, root_id, adj, ind2id, id2node, counter)
return adj, ind2id, id2node
N, Q = map(int, input().split())
S = input()
s = '(' + S + ')'
reader = Reader(list(s))
root = make_tree(reader)
adj, ind2id, id2node = traverse(root)
lca = LCA(len(id2node), adj, root=0)
for _ in range(Q):
x, y = map(int, input().split())
a = ind2id[x]
b = ind2id[y]
root = lca.query(a, b)
if root == 0:
print(-1)
else:
node = id2node[root]
print(f'{node.left} {node.right}')
norioc