結果
問題 | No.399 動的な領主 |
ユーザー |
|
提出日時 | 2024-08-15 14:00:00 |
言語 | PyPy3 (7.3.15) |
結果 |
WA
|
実行時間 | - |
コード長 | 3,826 bytes |
コンパイル時間 | 245 ms |
コンパイル使用メモリ | 82,380 KB |
実行使用メモリ | 98,304 KB |
最終ジャッジ日時 | 2024-08-15 14:00:12 |
合計ジャッジ時間 | 9,565 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 5 WA * 14 |
ソースコード
class HeavyLightDecomposition:#N,edgedef __init__(self,n,edge):self.n=nself.size=[1]*nself.par=[-1]*nque=[0]while que:#親とこの数を数える段階v=que.pop()if v>=0:#向かう点が0以上なら木を下る、0未満なら木を登る、下る際には今見ている辺の上向き、下向きを準備して親を定義するfor u in edge[v]:if u!=self.par[v]:que.append(~u)que.append(u)self.par[u]=velse:#上向きではこの数を伝搬するv=~vself.size[self.par[v]]+=self.size[v]self.head=[-1]*n#heavy辺上なら連結しているなかで一番上に位置する点self.head[0]=0self.order=[-1]*n#振り直された番号self.heavy_child=[-1]*n#自分とheavy辺を張られた子que=[0]cnt=0while que:v=que.pop()self.order[v]=cntcnt+=1mx=0for u in edge[v]:#heavy辺を決めるif u!=self.par[v] and mx<self.size[u]:mx=self.size[u]self.heavy_child[v]=ufor u in edge[v]:#light辺なのでheadは自分自身if self.par[v]!=u and self.heavy_child[v]!=u:self.head[u]=uque.append(u)if self.heavy_child[v]!=-1:self.head[self.heavy_child[v]]=self.head[v]que.append(self.heavy_child[v])def decomposition(self,u,v):#HL分解により処理された辺を返すpaths=[]while True:if self.order[u]>self.order[v]:u,v=v,uif self.head[u]!=self.head[v]:#自分を含むheavy辺が同じpaths.append((self.order[self.head[v]],self.order[v]+1))v=self.par[self.head[v]]else:paths.append((self.order[u]+1,self.order[v]+1))paths.append((self.par[u]+1,self.par[u]+2))return pathsN = int(input())edge = [[] for i in range(N)]for i in range(N-1):u,v = map(int, input().split())u-=1;v-=1edge[u].append(v)edge[v].append(u)HLD = HeavyLightDecomposition(N,edge)#print(HLD.order)"""#セグ木に乗せる例(距離)#セグ木の初期化if HLD.par[a] == b:#aが子なら整理した順序のorder上のaにaとbの辺の重さwを持たせるl[HLD.order[a]] = welse:#それの逆l[HLD.order[b]] = wseg = Segtree(l,0,f)#aが親で、a-b間の辺の重さをxに変更if HLD.par[a] == b:#aが子なら整理した順序のorder上のaにaとbの辺の重さxを持たせるl[HLD.order[a]] = xelse:#それの逆l[HLD.order[b]] = x#u~vの間の距離の和for e_u,e_v in HLD.decomposition(u,v):#分解した区間ごとに足すans += seg.query(e_u,e_v)"""data0 = [0]*(N+1)data1 = [0]*(N+1)# 区間[l, r)に x を加算def _add(data, k, x):while k <= N:data[k] += xk += k & -kdef add(l, r, x):_add(data0, l, -x*(l-1))_add(data0, r, x*(r-1))_add(data1, l, x)_add(data1, r, -x)# 区間[l, r)の和を求めるdef _get(data, k):s = 0while k:s += data[k]k -= k & -kreturn sdef query(l, r):return _get(data1, r-1) * (r-1) + _get(data0, r-1) - _get(data1, l-1) * (l-1) - _get(data0, l-1)Q = int(input())ans = 0for i in range(Q):a,b = map(int, input().split())a-=1;b-=1for j,k in HLD.decomposition(a,b):add(j+1,k+1,1)#print(HLD.decomposition(a,b))for i in range(1,N+1):tmp = query(i,i+1)ans += (1+tmp) * tmp //2print(ans)