結果

問題 No.2470 Gemini Tree(Ver.Jadeite)
ユーザー 👑 SPD_9X2
提出日時 2023-07-29 04:41:07
言語 PyPy3
(7.3.15)
結果
AC  
実行時間 2,745 ms / 5,000 ms
コード長 7,322 bytes
コンパイル時間 544 ms
コンパイル使用メモリ 82,432 KB
実行使用メモリ 188,268 KB
最終ジャッジ日時 2024-11-08 11:17:15
合計ジャッジ時間 61,389 ms
ジャッジサーバーID
(参考情報)
judge4 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 27
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

"""
Gemini Tree Ver.Jade (3)
:
DFS
DFS
E_cut
/
( E_cut )
"""
import sys
from sys import stdin
def segfunc(x,y):
return min(x,y)
class LazySegTree_RAQ:
def __init__(self,init_val,segfunc,ide_ele):
n = len(init_val)
self.segfunc = segfunc
self.ide_ele = ide_ele
self.num = 1<<(n-1).bit_length()
self.tree = [ide_ele]*2*self.num
self.lazy = [0]*2*self.num
for i in range(n):
self.tree[self.num+i] = init_val[i]
for i in range(self.num-1,0,-1):
self.tree[i] = self.segfunc(self.tree[2*i], self.tree[2*i+1])
def gindex(self,l,r):
l += self.num
r += self.num
lm = l>>(l&-l).bit_length()
rm = r>>(r&-r).bit_length()
while r>l:
if l<=lm:
yield l
if r<=rm:
yield r
r >>= 1
l >>= 1
while l:
yield l
l >>= 1
def propagates(self,*ids):
for i in reversed(ids):
v = self.lazy[i]
if v==0:
continue
self.lazy[i] = 0
self.lazy[2*i] += v
self.lazy[2*i+1] += v
self.tree[2*i] += v
self.tree[2*i+1] += v
def add(self,l,r,x):
ids = self.gindex(l,r)
l += self.num
r += self.num
while l<r:
if l&1:
self.lazy[l] += x
self.tree[l] += x
l += 1
if r&1:
self.lazy[r-1] += x
self.tree[r-1] += x
r >>= 1
l >>= 1
for i in ids:
self.tree[i] = self.segfunc(self.tree[2*i], self.tree[2*i+1]) + self.lazy[i]
def query(self,l,r):
self.propagates(*self.gindex(l,r))
res = self.ide_ele
l += self.num
r += self.num
while l<r:
if l&1:
res = self.segfunc(res,self.tree[l])
l += 1
if r&1:
res = self.segfunc(res,self.tree[r-1])
l >>= 1
r >>= 1
return res
N = int(stdin.readline())
s = list(stdin.readline()[:-1])
lis = [ [] for i in range(N) ]
elis = []
for i in range(N-1):
u,v,w = map(int,stdin.readline().split())
u -= 1
v -= 1
lis[u].append( (v,i) )
lis[v].append( (u,i) )
elis.append( (u,v,w) )
# G < B
g_all = 0
b_all = 0
for c in s:
if c == "G":
g_all += 1
else:
b_all += 1
if g_all > b_all:
for i in range(N):
if s[i] == "G":
s[i] = "B"
else:
s[i] = "G"
g_all,b_all = b_all,g_all
# dfs
stk = [0] #
serched_edge_num = [0] * N #v
is_serched = [False] * N
elis_dfs = [] #dfs(in,out 2)
visit_edge = [None] * N #
gnum_child = [0] * N #
bnum_child = [0] * N
while stk:
v = stk[-1]
if serched_edge_num[v] == 0: #
is_serched[v] = True
if s[v] == "G":
gnum_child[v] += 1
else:
bnum_child[v] += 1
if serched_edge_num[v] == len(lis[v]): #
if len(stk) >= 2: #
p = stk[-2] #
# gnum,bnum
gnum_child[p] += gnum_child[v]
bnum_child[p] += bnum_child[v]
# visit edge elis_dfs, 1,2,, 3eidx , 4in/out
elis_dfs.append( ( p , v , visit_edge[v] , False) )
stk.pop()
else: #
nexv,eidx = lis[v][serched_edge_num[v]]
serched_edge_num[v] += 1
# print (nexv,eidx)
if is_serched[nexv]: #
pass
else:
stk.append(nexv)
elis_dfs.append( (v,nexv,eidx,True) )
visit_edge[nexv] = eidx
# print (elis_dfs)
# print (gnum_child)
# print (bnum_child)
#
label = [None] * N
label_stk = []
for p,c,eidx,is_in in elis_dfs:
if gnum_child[c]+bnum_child[c] == b_all: #
if is_in:
for p2,c2,_,_ in elis_dfs:
label[p2] = eidx
if c == c2:
break
label[c2] = eidx
for p2,c2,_,_ in reversed(elis_dfs):
label[p2] = eidx
if c == c2:
break
label[c2] = eidx
elif gnum_child[c] + bnum_child[c] == g_all: #G
if is_in:
label_stk.append(eidx)
label[c] = eidx
else:
label_stk.pop()
else:
if label_stk:
label[p] = label[c] = label_stk[-1]
# print (label)
# eidx -> elis_dfs2
ref_eidx2ed = [ [None,None] for i in range(N-1) ]
for i in range(len(elis_dfs)):
p,c,eidx,is_in = elis_dfs[i]
if is_in:
ref_eidx2ed[eidx][0] = i
else:
ref_eidx2ed[eidx][1] = i
# cut0
first_seg_state = [float("inf")] * (2*N-2)
for i,(p,c,eidx,is_in) in enumerate(elis_dfs):
if is_in and (gnum_child[c]+bnum_child[c] in (b_all,g_all)):
first_seg_state[i] = 0
# (/)
seg = LazySegTree_RAQ( first_seg_state , segfunc , float("inf") )
#
Q = int(stdin.readline())
ANS = []
if g_all == 0:
for i in range(Q):
print (0)
sys.exit()
for loop in range((N-1) + Q):
if loop < N-1: #
eidx,a = loop,elis[loop][2]
else:
eidx,a = map(int,stdin.readline().split())
eidx -= 1
lidx,ridx = ref_eidx2ed[eidx] #
p,c,_,_ = elis_dfs[lidx] #2
if label[p] == label[c] == None: #
seg.add(lidx,ridx,a*(g_all-gnum_child[c]))
if lidx > 0:
seg.add(0,lidx,a*gnum_child[c])
if ridx < 2*N-2:
seg.add(ridx,2*N-2,a*gnum_child[c])
else:
if (gnum_child[c] + bnum_child[c]) * 2 < N:
g_min_side = gnum_child[c]
b_min_side = bnum_child[c]
else:
g_min_side = g_all - gnum_child[c]
b_min_side = b_all - bnum_child[c]
nlabel = label[p] if label[p] != None else label[c]
nlabel_idx = ref_eidx2ed[nlabel][0]
seg.add(0,2*N-2,a*g_min_side)
seg.add(nlabel_idx,nlabel_idx+1, a*(b_min_side-g_min_side) )
# ANS
if loop >= N-1:
ans = seg.query(0,2*N-2)
ANS.append(ans)
# print ( p,c,label[p],label[c], [seg.query(i,i+1) for i in range(2*N-2) ] )
print (*ANS,sep="\n")
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0