題目
先考慮兩棵樹怎麼做。
我們在第二棵樹的每乙個點u
uu上再掛乙個點u′u'
u′,他們的距離為第一棵樹上的dep
udep_u
depu。
那麼在第二棵樹上的兩點u′,
v′
u',v'
u′,v
′的距離就是兩棵樹上距離總和-u,v
u,vu,
v在第一棵樹上的lca
lcalc
a的深度×
2\times 2
×2考慮列舉這個lca
lcalc
a,那麼答案就應該是lca
lcalc
a的兩個不同子樹s1,
s2
s1,s2
s1,s
2,求u′∈
s1,v
′∈s2
u'\in s1,v'\in s2
u′∈s1,
v′∈s
2的在第二棵樹上的dis
(u′,
v′
)dis(u',v')
dis(u′
,v′)
的最大值-lca
lcalc
a的深度×
2\times 2
×2。兩個點集間的最長距離的兩個端點一定可以是在兩個點集各自的直徑端點中各取乙個。
所以就動態維護點集直徑即可,
時間複雜度o(n
logn)
o(n\log n)
o(nlogn)
如果o (1
)lca
o(1)lca
o(1)lc
a的話就是預處理o(n
logn)
o(n\log n)
o(nlogn)
解答o (n
)o(n)
o(n)
再加入一顆樹。
那麼在第三顆樹上邊分治,把乙個點集s
ss分成兩個集合s1,
s2
s1,s2
s1,s2,
那麼我們在第一棵樹上建立點集s
ss的虛樹,
然後對於第一棵樹和第二棵樹我們用之前的做法不過現在我們要更新答案,
兩個端點不能同在s1s1
s1或同在s2s2
s2。簡單dpdp
dp一下即可。
時間複雜度o(n
logn∗
sort
(n)+
nlogn
)o(n\log n * sort(n) + n\log n)
o(nlogn∗
sort
(n)+
nlogn)
用基排好像可以o(n
logn)
o(n\log n)
o(nlogn)
的理性愉悅一下。
我居然只是小小的調了幾個錯而已。
這**比紫荊花之戀和希望都長,應該是我目前最長的**了 acc
od
e\mathrm
accode
#include
#define maxn 400005
#define ll long long
#define ct const
#define lim 19
#define rep(i,j,k) for(int i=(j),lim=(k);i<=lim;i++)
#define per(i,j,k) for(int i=(j),lim=(k);i>=lim;i--)
#define adj(i,u) for(int i=info[u],v;i;i=prev[i])
using
namespace std;
char cb[
1<<16]
,*cs=cb,
*ct=cb;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<16,stdin),cs==ct)?0:*cs++)
template
<
class
t>
void
read
(t &res)
int n,lg[maxn]
;ll ans;
void
prepare_st
(int mn[lim]
[maxn]
,int
*dep,
int n)
namespace tree1
void
dfs(
int u,
int ff)
void
init()
intlca
(int u,
int v)
ll dis
(int u,
int v)
}using tree1::dis;
int ar[maxn]
;namespace tree2
void
dfs(
int u,
int ff)
void
init()
intlca
(int u,
int v)
bool
cmp(ct int
&u,ct int
&v)int f[maxn][2
][2]
;void
merge
(int u,
int v)
}void
newnode
(int u)
void
solve()
q[++r]
=ar[i]
,newnode
(ar[i]);
}for
(int p=
0;r;p=q[r--])
if(p)
merge
(q[r]
,p);}}
namespace tree3
int fir[maxn]
,tar[maxn<<1]
,nxt[maxn<<1]
,cnte=1;
void
add(
int u,
int v,ll w=0)
void
lin(
int u,
int v,ll w=0)
int n,sz[maxn]
;bool vis[maxn]
;void
build
(int u,
int ff)
void
dfs(
int u,
int ff,
int tsz,
int&mn,
int&rt)
}int
gert
(int u,
int tsz)
void
ser(
int u,
int ff,ll d,
int tp)
void
solve
(int u)
void
init()
}int
main()
UOJ 347 WC2018 通道 邊分治
傳送門 就是求兩個點 a,b 使得 dis 1 a,b dis 2 a,b dis 3 a,b 最大 對第一棵樹邊分治 那麼變成 d 1 a d 1 b dis 2 a,b dis 3 a,b 最大 並且 a,b 屬於邊分開的不同的集合 s,t 對於一條邊,算經過這條邊的路徑的答案 點分治不方便的就...
WC2018 通道 與 CTSC2018 暴力寫掛
兩個都給出點分治的做法,看起來邊分治不光跑的慢還沒什麼不可替代性?暴力寫掛 考慮那個式子有兩個不同樹上的 operatorname 不好處理,考慮怎麼換成乙個 由於 dis x,y deep x deep y 2deep operatorname x,y 於是用 dis 代換 dfrac dis x...
WC2018 即時戰略
繼紫荊花之戀後第二道蒟蒻所知道的會動的樹的點分治 題意 給你一顆未知的樹,你只知道1,你可以詢問explore u,v 得到 u,v 路徑上的第乙個點,請你在有限的詢問次數內確定這一棵樹 首先隨機化一下訪問次數,這樣就不會被奇奇怪怪地卡掉了 雖然出題人也是隨的資料 鏈,詢問次數限制n logn,記錄...