1. 程式人生 > >[BZOJ2325][ZJOI2011]道館之戰(樹剖+線段樹)

[BZOJ2325][ZJOI2011]道館之戰(樹剖+線段樹)

Address

洛谷P4679
BZOJ2325

Solution

先樹剖,把樹轉成序列。然後線段樹上每個點維護 8 8 個值:
z 00 z_{00}

:從對應區間左端點的 A A 區域走到右端點的 A A 區域經過的最多格子數,如果不連通則為 0
0

z 01 z_{01} :從對應區間左端點的 A A
區域走到右端點的 B B 區域經過的最多格子數,如果不連通則為 0 0
z 10 z_{10} :從對應區間左端點的 B B 區域走到右端點的 A A 區域經過的最多格子數,如果不連通則為 0 0
z 11 z_{11} :從對應區間左端點的 B B 區域走到右端點的 B B 區域經過的最多格子數,如果不連通則為 0 0
f r 00 fr_{00} :從對應區間左端點的 A A 區域開始走經過的最多格子數。
f r 01 fr_{01} :從對應區間左端點的 B B 區域開始走經過的最多格子數。
f r 10 fr_{10} :從對應區間右端點的 A A 區域開始走經過的最多格子數。
f r 11 fr_{11} :從對應區間右端點的 B B 區域開始走經過的最多格子數。
下面定義運算:
x y = { x + y x , y 0 0 ELSE x\bigoplus y=\begin{cases}x+y&x,y\ne0\\0&\text{ELSE}\end{cases}
線段樹左右子節點合併時( l c lc r c rc 分別為 u u 的左右子節點):
z 00 [ u ] = max ( z 00 [ l c ] z 00 [ r c ] , z 01 [ l c ] z 10 [ r c ] ) z_{00}[u]=\max(z_{00}[lc]\bigoplus z_{00}[rc],z_{01}[lc]\bigoplus z_{10}[rc])
z 01 [ u ] = max ( z 00 [ l c ] z 01 [ r c ] , z 01 [ l c ] z 11 [ r c ] ) z_{01}[u]=\max(z_{00}[lc]\bigoplus z_{01}[rc],z_{01}[lc]\bigoplus z_{11}[rc])
z 10 [ u ] = max ( z 10 [ l c ] z 00 [ r c ] , z 11 [ l c ] z 10 [ r c ] ) z_{10}[u]=\max(z_{10}[lc]\bigoplus z_{00}[rc],z_{11}[lc]\bigoplus z_{10}[rc])
z 11 [ u ] = max ( z 10 [ l c ] z 01 [ r c ] , z 11 [ l c ] z 11 [ r c ] ) z_{11}[u]=\max(z_{10}[lc]\bigoplus z_{01}[rc],z_{11}[lc]\bigoplus z_{11}[rc])
f r 00 [ u ] = max ( f r 00 [ l c ] , max ( z 00 [ l c ] f r 00 [ r c ] , z 01 [ l c ] f r 01 [ r c ] ) ) fr_{00}[u]=\max(fr_{00}[lc],\max(z_{00}[lc]\bigoplus fr_{00}[rc],z_{01}[lc]\bigoplus fr_{01}[rc]))
f r