WC2018 通道(邊分治套虛樹)

2021-10-02 05:57:13 字數 3658 閱讀 7539

題目

先考慮兩棵樹怎麼做。

我們在第二棵樹的每乙個點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

log⁡n)

o(n\log n)

o(nlogn)

如果o (1

)lca

o(1)lca

o(1)lc

a的話就是預處理o(n

log⁡n)

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

log⁡n∗

sort

(n)+

nlog⁡n

)o(n\log n * sort(n) + n\log n)

o(nlogn∗

sort

(n)+

nlogn)

用基排好像可以o(n

log⁡n)

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,記錄...