LCT總結——應用篇(附題單)(LCT)

爲了優化體驗(實際上是強迫症),蒟蒻把總結拆成了兩篇,方便不一樣學習階段的Dalao們切換。php

LCT總結——概念篇戳這裏html

題單

灰常感謝XZY巨佬提供的強力資磁!(可參考XZY巨佬的博客總結
題單對於系統地學習一個知識點仍是有好處的。
因此蒟蒻蒐集了各處的LCT題目(其實做爲近年新興的知識點,現有的好題不是不少,有些題樹剖也可作
大概按細化分類進行整理(類比下面的幾個細化知識點,會有重複的列舉)
同一類中的題目也大概按難度遞增吧(太弱了,對每一個題的難度定位或許有不許的地方,歡迎討論!)數組

維護鏈信息(LCT上的平衡樹操做)

動態維護連通性&雙聯通份量(能夠說是並查集的升級,由於並查集只能連不能斷)

維護邊權(經常使用於維護生成樹)

維護子樹信息

維護樹上染色聯通塊

特殊題型

操做升級!(模板之外的細化總結)

維護鏈信息(LCT上的平衡樹操做)

思路與模板基本都很像了,就不展開討論了網絡

例題1

洛谷P1501 [國家集訓隊]Tree II(點擊進入題目)
感受難度評定也高了點吧
有了鏈上乘法和鏈上加法,那確定是像線段樹區間修改那樣使用懶標記了。
放標記的作法來自[模板]線段樹2
那裏發題解的Dalao們都講得挺好的,本蒟蒻參考一下。
蒟蒻的題解在這裏數據結構

例題2

洛谷P3203 [HNOI2010]彈飛綿羊(點擊進入題目)
略帶一點思惟,可是代碼比模板還簡單。。。。。。
在LCT模板基礎上進行靈活運用,可使代碼和程序都作到高效。
蒟蒻的題解在這裏函數

例題3

洛谷P4332 [SHOI2014]三叉神經樹
沒有那麼裸了,仔細分析並利用好題目的性質
蒟蒻的題解在這裏學習

動態維護連通性&雙聯通份量

維護連通性?findroot判一下就好啦!屬於模板範疇
至於雙連通份量,LCT好像只能資磁加邊。。。。。。
LCT中的每一個點其實表明的是一個雙連通份量,維護每一個點屬於哪一個雙連通份量須要在外面弄一個並查集維護。
加邊時,若是兩點不連通就link;
若是連通就說明有環,把環縮成一個點,在並查集裏也所有合併在一塊兒
其中要注意不少細節,具體就看下下面例題2的代碼吧優化

例題1

洛谷P3950 部落衝突(點擊進入題目)
正解不是LCT。。。。。。
只是這裏用LCT的思路很是簡單甚至於無腦。。。。。。
蒟蒻題解code

例題2

洛谷P2542 [AHOI2005]航線規劃(點擊進入題目)
基礎的動態維護雙連通份量,具體就看看題解吧
蒟蒻題解htm

維護鏈上的邊權信息(生成樹)

普通LCT維護點權,那對於邊權呢?好比要獲取一條路徑上最長的邊,等等。
這種維護的最經典的應用,大概就是動態維護一顆最小/大生成樹了(須要獲取邊長度等信息)。
我起初有一種想法。
一棵樹,除了根節點,每一個節點有且僅有一條父邊。
那麼若是咱們只要邊的信息,可不能夠就把LCT中的點的點權當成父邊的邊權呢?
在其它很多數據結構中好像是能夠這樣作的。
只不過LCT性質很是特殊。一旦換了根,原先邊的父子關係就破壞了。因此並不能這樣作。
那又如何是好呢?
我在網上看到有些博客介紹的方法,是把邊置於LCT外,而後在LCT節點中維護父邊和重子邊的編號,須要更新信息時從外部獲取,在access,link,cut時額外更改。
這樣好像挺麻煩的,要維護那麼多東西。
另外一種更抽象的作法,也是我要分享的,就是兩個字——拆邊,把邊視做爲一個點,向該邊的兩個端點連兩條邊。
只須要維護邊權的時候,邊權存在LCT中表明邊的點權裏,由於不須要維護真正的點權,因此LCT中的表明點的點權能夠設成空的(0),不會影響信息的正確性。因而就變成了維護點權。
固然了,原先咱們的link和cut是對於兩個點的,如今有點不同了(由於兩點之間又多了一個表明邊的點)
update:發現以前描述的寫法有問題,且並不能優化多少常數,在這裏更正一下
寫法就是link/cut兩次,好比

link(e[i].id,e[i].x);link(e[i].id,e[i].y);
    cut(e[i].id,e[i].x);cut(e[i].id,e[i].y);

例題一

洛谷P4180 [BJWC2010]次小生成樹
其實這道題用LCT不是正解,不過是可作的(update:我後來又寫了LCT),放在這裏一下吧。
用LCT維護最小生成樹,再去枚舉非樹邊嘗試替換樹邊,更新最優答案。
TPLY巨佬也用LCT作的(某問題致使常數巨大?),他的題解在這裏
蒟蒻題解在這裏

例題二

洛谷P2387 [NOI2014]魔法森林
我太弱啦!這種雙關鍵字的維護我是真的沒有思路,邊看着題解邊打出來的。orz XZY&XZZ兩位巨佬,題解點贊!
不過做爲LCT維護邊權的好題目仍是值得分享。
蒟蒻題解在這裏

維護虛子樹信息總和與原樹信息總和

有時候,咱們須要的並非維護鏈的信息,而是子樹的信息。要知道,LCT是長於維護鏈的信息,而弱於維護子樹信息(這方面不得不認可樹剖的用處了,還要趕忙學)。然而動態的連邊和斷邊,又不得不要求咱們使用LCT來維護。

其實,咱們仍是不會一籌莫展的。

維護子樹信息總和的一些常見題型,無非就是詢問整棵(原樹中的)子樹的總大小、權值總和、最值之類的東西。
咱們已經能夠經過輔助樹Splay來獲知Splay中的實子樹(也就是原樹中的一條鏈)的信息總和。
既然原樹的邊只有實與虛,子樹也只有實與虛,那麼若是要想維護好原樹的信息總和,咱們是否是首先要知道虛子樹的信息總和?
注:如下設虛子樹信息總和用數組si表示,原樹信息總和用s表示。此處si[x]只包含x全部虛子樹(經過輕邊指向x)的信息總和,而s[x]其實是在LCT中的全部兒子的信息總和(包括輔助樹Splay中相對的左右兒子的總和與被輕邊所指的絕對的虛子樹的總和)。
那麼若是咱們肯定了si[x]的值,是否是就知道了s[x]的值了?實加虛嘛!
這就是pushup,代碼

inline void pushup(int x){
    s[x]=s[c[x][0]]+s[c[x][1]]+si[x]+1;//大小總和,注意別漏了+1,本身也要算上
    //或者
    s[x]=s[c[x][0]]+s[c[x][1]]+si[x]+v[x];//權值總和,本身一樣也要算上
}

先不對這種方法是怎樣來的這個問題追本溯源,那咱們就能夠直接考慮si如何維護了。
仍是直接假設咱們已經提早維護好了si吧。
很顯然,si的變化取決於虛實邊的變化,因此如今咱們只考慮LCT中的每一個操做會對虛實邊產生怎樣的影響。

  • splay(x):顯然這一操做只會改變節點在輔助樹Splay中的相對位置,並不會對樹中的虛子樹信息產生任何影響。過程當中的pushup會正確地更新s。
  • access(x):這個時候,咱們發現,循環中每一次splay(x)後,咱們更改了x的右子樹,也就是更改了虛實邊,那麼會對信息產生影響。
    這裏的影響,無非就是獲得了一個虛兒子,失去了一個虛兒子,總和沒有改變。
    因而直接改就好啦,si加上原來右兒子的s,再減去新的右兒子的s。
    與原模板略有不一樣的代碼
inline void access(int x){
    for(int y=0;x;x=f[y=x]){
        splay(x);
        si[x]+=s[c[x][1]];
        si[x]-=s[c[x][1]=y];
        pushup(x);
//若是pushup只是更新原樹信息總和s的話,甚至這裏能夠不寫,畢竟加一個減一個,和沒變
    }
}
  • makeroot(x):並沒有影響。雖然樹的形態翻轉了,可是翻轉的只是實鏈。
  • findroot(x):顯然無影響(跳左兒子又沒改變樹的形態)
  • split(x,y):顯然無影響(除了調用三個函數外什麼都沒幹)
  • link(x,y):這就有影響了。y多了一個輕邊指向兒子x,那麼s[y],si[y]都加上s[x]。注意,多了一個子樹,那麼y在LCT中的祖先的s也都要加上s[x]的值,卻沒有獲得更新。咱們在加上s[x]前,須要額外地把y轉到根(access(y)+splay(y)),y就沒有祖先了,再加,就不會影響信息的正確性了。
    與原模板略有不一樣的代碼
//保證連邊合法
inline void link(int x,int y){
    split(x,y);//這裏不是提取x-y的路徑的意思,是makeroot+access+splay的偷懶寫法
    si[f[x]=y]+=s[x];
    pushup(y);
}
//不保證
inline bool link(int x,int y){
    makeroot(x);
    if(findroot(y)==x)return 0;//access+splay已完成
    si[f[x]=y]+=s[x];
    pushup(y);
    return 1;
}
  • cut(x,y):無影響,斷掉的是一條重邊,pushup(y)更新s[y]就好啦。

分析到此完畢。其實好像也就只改了一點點地方。。。。。。不過思路是很巧妙的,值得用心體會。

補充一句,若是要維護子樹裏的最值,一個套路是在每一個節點開一個平衡樹維護該節點全部虛子樹的最值,以便進行查詢和更改。

例題一

洛谷P4219 [BJOI2014]大融合(點擊進入題目)
當學會了LCT維護子樹信息和之後,這題就變得有些裸了。。。。。。
蒟蒻題解在這裏

例題二

洛谷U19464 山村遊歷(Wander)(點擊進入題目)
注:此題爲WC模擬賽試題,版權歸出題人Philipsweng全部。小蒟蒻以爲這題出得很不錯,因而上傳至洛谷我的題庫,做爲例題與你們分享。數據自測,若有問題歡迎反饋。
題目簡述:
沒有。。。。。。這是一個閱讀題,簡述的話就等於告訴你怎麼作了
仔細讀一下題目吧,這道題水平挺高的。
思路分析:
也有點複雜
然而分析完了之後,又變成裸的了。。。。。。
算了,仍是單獨建一篇隨筆吧。
蒟蒻題解在這裏

維護樹上染色聯通塊

維護方法要視具體狀況分析
可能能夠開一個LCT而後把同色的點連起來,這樣作思路很簡單,但實現起來受侷限
也可能有多少顏色就開多少個LCT,而後在對應顏色的LCT中連上
升級操做:修改點的顏色
須要轉化模型,可參考下面例題2
再次升級操做:修改鏈爲同一種顏色
Link-Cut-Memphis(霧
看一下發明者Memphis巨佬的博客
以上兩種操做都是在ZJOI2018交流課上聽到的Orz

例題一

洛谷P3703 [SDOI2017]樹點塗色(點擊進入題目)
維護連通塊並不麻煩,只是思惟難度超大。。。。。。
不會樹剖,焉知非福?
蒟蒻的題解

例題二

洛谷SP16549 QTREE6 - Query on a tree VI(點擊進入題目)
一直都把邊化爲子節點,此次來把點化爲父邊(霧
蒟蒻的題解

特殊題型

有一類題目是真的毒瘤,怪異到都幾乎認不出它的真面目
彷佛並不能把它們歸爲任何一類LCT題型或者任何一種套路
只好仔細分析題目,發現題目自己的特殊性,再轉化爲LCT模型解決
然而我什麼都分析不出來啊QwQ

例題一

洛谷P3613 睡覺困難綜合徵
把起牀困難綜合症——一個按位貪心的題目,完美地套在了LCT中
蒟蒻題解

例題二

洛谷P3348 [ZJOI2016]大森林
新技能get:虛點
離線的轉移思路也極爲巧妙
蒟蒻題解

例題三

洛谷P4338 [ZJOI2018]歷史
ZJOI惟一可作題TAT
不來一些大力結論,根本作不下去。。。。。。
蒟蒻題解

相關文章
相關標籤/搜索