CTSC2018 暴力寫掛 邊分樹合併

2022-02-05 01:11:41 字數 3014 閱讀 3209

[ctsc2018]暴力寫掛

題面不錯

給定兩棵樹,兩點「距離」定義為:二者深度相加,減去兩棵樹上的lca的深度(深度指到根節點的距離)

求最大的距離。

解決多棵樹的問題就是降維了。

經典的做法是邊分樹合併

邊分樹結構類似0/1 trie

就是把邊分樹對於每個點拆開路徑

合併兩棵邊分樹同時可以得到兩個邊分樹之間點對的路徑的資訊

感覺有點類似線段樹合併。

根據「貓樹」思想,兩點間的路徑一定經過邊分樹上lca的那條邊。(u,v不相等)

我們考慮在這個lca處統計貢獻

具體地,先對1樹進行邊分治

每個點初始的邊分樹是一條鏈,考慮對每個點構造出這個邊分樹。

開始只有根。

其實就是記錄分治時候是在那個位置。

定義連線分治重心root深度較小的連通塊為右部點,另乙個為左部點

儲存每個點作為左部點還是右部點

在每個之前最後乙個加入位置lasi 下面加入左兒子或者右兒子。

在lasi位置保留這個資訊vl,vr。初始是-inf

表示子樹裡所有的真實點在邊分治這一層的左部、右部最大值。

左部點貢獻權值:dis[x]

右部點貢獻:dis[x]-dis[lca]

因為lca一定在右部點。

在第二棵樹上列舉lca z ,子樹邊分樹合併上來(就類似樹上的線段樹合併)

合併時候max(vl(x)+vr(y)-dis'[z],vr(x)+vl(y)-dis'[z])更新答案。

然後vl(x)=max(vl(x),vl(y)) vr同理。按位取max

(注意沒有pushup,因為這裡是分治結構

可以發現,任意點對(u,v),一定在第二棵樹上的lca位置被考慮到,邊分樹合併時候,會在邊分樹lca處嘗試做出貢獻。

大概初始的分治樹:

**:注意:

1.邊分樹2*n個點,邊數4*n,

邊分治的vis陣列開4*n。

2.處理u,v重合情況。

//

luogu-judger-enable-o2

//luogu-judger-enable-o2

#include#define reg register int

#define il inline

#define fi first

#define se second

#define mk(a,b) make_pair(a,b)

#define numb (ch^'0')

using

namespace

std;

typedef

long

long

ll;template

il void rd(t &x)

template

il void output(t x)

template

il void ot(t x)

template

il void prt(t a,int st,int nd)

namespace

miracle

}t[n*30

];ll ans;

inttot;

intrt[n];

ll nd;

//now dis of lca'(u,v)

int merge(int x,int

y)namespace

tr1e[

4*n];

int hd[2*n],cnt=1

;void add(int x,int y,int

z)int

cur;

int d[2*n];

void rebuild(int x,int

fa)}

void dfs(int x,int

fa)}

intnowsz;

int vis[4*n];

int las[2*n];

int root,sz[2*n];

intmi;

void fin(int x,int

fa) sz[x]+=sz[y];

}}void dfs2(int x,int fa,int id,int typ)

else

}for(reg i=hd[x];i;i=e[i].nxt)

}void divi(int

x)

void che(int

x)void

main()

cur=n;

rebuild(

1,0);

//cout<

);

//prt(dis,1,cur);

//prt(d,1,cur);

//cout<

; nowsz=cur;

for(reg i=1;i<=n;++i)

divi(1);

//che(3);

//che(4);

//cout<

}namespace

tr2e[

2*n];

int hd[n],cnt=0

;void add(int x,int y,int

z)void dfs(int x,int

fa) ans=max(ans,tr1::dis[x]-dis[x]);

}void

main()

ans=-inf;

dfs(

1,0);}}

intmain()

}signed main()

/*author: *miracle*

date: 2019/4/13 19:58:12

*/

合併時候,就是利用分治樹的結構層層分離點對,在分治邊的位置貢獻。

進行降維。

CTSC2018 暴力寫掛

題目 邊分治 虛樹 雙倍的快樂 這個柿子裡有兩個 lca 我們考慮魔改一下前面的 operatorname 為了方便邊分,我們考慮把 operatorname 去掉變換為樹上距離 經過一番魔改,這個柿子變成了 frac operatorname 至於第二棵樹上的 operatorname 我們只能考...

CTSC2018 暴力寫掛

題目鏈結 ctsc2018 暴力寫掛 做法 dep x dep y dep lca x,y dep lca x,y frac dep x dep y 2dep lca x,y dep x dep y 2dep lca x,y frac dis x,y dep x dep y 2dep lca x,y...

WC2018 通道 與 CTSC2018 暴力寫掛

兩個都給出點分治的做法,看起來邊分治不光跑的慢還沒什麼不可替代性?暴力寫掛 考慮那個式子有兩個不同樹上的 operatorname 不好處理,考慮怎麼換成乙個 由於 dis x,y deep x deep y 2deep operatorname x,y 於是用 dis 代換 dfrac dis x...