鑑於lca本人已經寫過此題命題報告,所以可以認為本文是命題報告的註解以及實現指南。
好神仙的一道題,前前後後總共耗了我差不多三整天時間。
最開始看到這題是集訓隊互測loj上同步賽的現場,當時就覺得很吸引人。
然而並不會做,膜了一波sol,然而還是不會。
後來zjoi2018r2第二天scape講題時又提到了此題,還是不會。
暑假裡嘗試過一波,並沒有什麼進展。
現在強推了一波,終於乾掉了此題。
題解部分自此開始。
很多lca命題報告裡有的東西不會再贅述。
所以假定閱讀此文的讀者已經仔細閱讀過lca的命題報告,對原文中的各個定理已經很熟悉了。
符號盡量會與原**統一。
我的**在此
想要解決此題,首先要引入笛卡爾樹的概念,子任務2對此有大致的介紹。
然後就是解決靜態問題,可以看子任務3。
子任務4到7並不是解決本題的必讀部分,可以直接跳到子任務8,9的部分。
首先,原文中有一句」笛卡爾樹可以離線維護來降低常數「,先介紹一下我用到的靜態操作,以便後文使用。
void ini()
用於建立靜態的笛卡爾樹,可以按編號從小到大來建立,使用並查集來維護只考慮前i個點構成的「笛卡爾森林」中某個點所在樹的根。
int lca(int x,int y)
用於查詢當前的笛卡爾樹中x和y的lca。
int getv(int x,int y)
用於查詢原樹中x到y的路徑上離x最近的那個點。
如果x是y的祖先,那麼就在x的兒子裡二分y的dfn序,否則返回x的爸爸。
int getson(int u,int v)
用於查詢當前笛卡爾樹中從u往上爬到v之前的最後乙個點。
對於這個問題,我是使用重鏈剖分,從u往上到v的o(l
ogn)
o(logn)
o(logn
)條重鏈裡,對於不包括點v本身的重鏈,直接用該重鏈裡的最淺點來更新。
bool cke(int x,int y)
其中u是v在笛卡爾樹上的祖先。
用於判定y能否一步跳到x。
一方面是回答詢問的需要,另一方面,實現了這個函式,可以輔助debug。
然後考慮如何維護f(t
)f(t)
f(t)
。如果是靜態問題,原報告中已經有過介紹,其中「每個點對應的底端」應該是指某個點b到fc(
t)(b
)f_(b)
fc(t)
(b)在原樹中的路徑上,離fc(
t)(b
)f_(b)
fc(t)
(b)最近的乙個點。
如果是動態加葉子,對於加葉子操作(u,v),原文中並沒有提到ff(
t)(v
)f_(v)
ff(t)
(v)應該如何維護,實際上ff(
t)(v
)=ff
(t)(
u)
f_(v)=f_(u)
ff(t)
(v)=
ff(t
)(u
)(2020.03.17upd:經指出該等式右邊應為ff(
t)(g
etso
n(v,
u)
)f_(getson(v,u))
ff(t)
(get
son(
v,u)
)),證明就是注意到在c(t
)c(t)
c(t)
上乙個點到根的路徑構成乙個有序序列。
關於處理加入v後對其它點在f(t
)f(t)
f(t)
裡的父親的影響,先要建立乙個類似於將f(t
)f(t)
f(t)
三度化的g(t
)g(t)
g(t)
,跟配對堆有點像,原文介紹過g(t
)g(t)
g(t)
的定義。
然後要處理v對其它點的影響,就是在g(t
)g(t)
g(t)
裡找到u往上的第一條權為一的邊,整條鏈切下來接到v下面。然後u爬到這條鏈頂在(c(
t)
(c(t)
(c(t
)上的爸爸,繼續前述操作,直到鏈頂大於v。
但是直接切下來一條鏈是有問題的,除了鏈頂的邊權會1變0,還可能有別的邊0變1,這一點是原文所沒提到的。
想要解決這個問題,可以先發現一條性質:每個點在g(t
)g(t)
g(t)
裡往下最多有一條權為0的邊。
現在的目標就是找出這條邊。
記該點為x,則我們所求的點就是fc(
t)(x
)f_(x)
fc(t)
(x)和x在原樹中所「夾」出來的連通塊中的最大值。
用前述靜態操作來說,就是getson(getv( x , fc(
t)(x
)f_(x)
fc(t)
(x) ),x)。
最後考慮查詢。
對於詢問(x,y),我們需要先找出lca(x,y),然後把詢問拆成query(x,lca)和query(y->lca)。
其中query要返回兩個值,一是爬到lca前的最後乙個點,二是爬到這個點的步數。
杰哥私房題 校門外的大樹
問題描述 某校大門外長度為 l 的馬路上有一排樹,每兩棵相鄰的樹之間的間隔都是 1 公尺。我們 可以把馬路看成乙個數軸,馬路的一端在數軸 0 的位置,另一端在 l 的位置 數軸上的每 個整數點,即 0,1,2,l,都種有一棵樹。由於馬路上有一些區域要用來建地鐵。這些區域用它們在數軸上的起始點和終止點...
每日一題 校門外的樹
校門外的樹 某校大門外長度為l的馬路上有一排樹,每兩棵相鄰的樹之間的間隔都是1公尺。我們可以把馬路看成乙個數軸,馬路的一端在數軸0的位置,另一端在l的位置 數軸上的每個整數點,即0,1,2,l都種有一棵樹。由於馬路上有一些區域要用來建地鐵。這些區域用它們在數軸上的起始點和終止點表示。已知任一區域的起...
loj6402 校門外的樹 dp,多項式求逆
慶祝一下,第乙個我自己做出來的,多項式的題 沒辦法,我太弱 雖然用了2個小時才想出來,但這畢竟是0的突破 首先宣告,雖然我寫的題解很長,但是大部分都是證明和廢話 第一步,轉化題意 用時30min 乙個1 n的全排列 p 如果存在 i 問所有p的所有排列方案,最後聯通塊的大小的乘積,的和。因為原題中 ...