[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...