UOJ 347 WC2018 通道 邊分治

2022-05-07 18:39:11 字數 2427 閱讀 7162

傳送門

就是求兩個點 \(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\)

對於一條邊,算經過這條邊的路徑的答案

點分治不方便的就是同一棵子樹的容斥,而邊分治不用考慮

直接邊分治顯然菊花就卡掉了

所以我們要轉二叉樹

具體來說就是把乙個點的兒子建一棵線段樹,新增虛擬節點,點權為其父親的點權,只有線段樹的葉子節點有邊權

對第二棵樹建虛樹

建出 \(s|t\) 的虛樹

變成 \(d_1(a)+d_2(a)+d_1(b)+d_2(b)+dis_3(a,b)-2d_2(lca_2(a,b))\)

\(a\in s,b\in t\)

列舉 \(lca\) 那麼變成求乙個類似於 \(w_1(a)+w_2(b)+dis_3(a,b)\) 的最大值

第三棵樹不需要什麼,上式類似於乙個求最長鏈的東西

而兩棵子樹合併之後的最長鏈的端點一定是原來兩棵樹的最長鏈的端點

所以只需要在第三棵樹上求距離就好了,然後在第二棵樹上 \(dp\) 維護

奉上 \(7.6kb\) 大常數**

# include using namespace std;

typedef long long ll;

const int maxn(1e5 + 5);

int cnt1, cnt2, lef[maxn], rig[maxn];

ll ans, val[maxn];

namespace tree1 edge[maxn << 1];

inline void add(int u, int v, ll w) , first[u] = cnt++;

edge[cnt] = (edge), first[v] = cnt++;

} inline int min(int x, int y)

void dfs(int u, int ff)

} inline int lca(int u, int v)

inline ll dis(int u, int v)

void init()

}namespace tree2 edge[maxn << 1], edg[maxn << 1];

inline void add1(int u, int v, ll w) , first[u] = cnt++;

edge[cnt] = (edge), first[v] = cnt++;

} inline void add2(int u, int v) , head[u] = cnt++;

} inline int min(int x, int y)

void dfs(int u, int ff)

} inline int lca(int u, int v)

struct info

inline bool operator <(info b) const

} f1[maxn], f2[maxn];

inline info operator +(info a, info b)

inline info merge(info a, info b)

void init()

inline int cmp(int x, int y)

void calc(int u, ll add)

} void solve(ll add)

calc(sta[1], add);

for (i = 1; i <= len; ++i) val[que[i]] = vis[que[i]] = 0;

}}namespace tree3 edge[maxn * 8], edg[maxn << 1];

inline void add1(int u, int v, ll w) , head[u] = cnt++;

edg[cnt] = (edge), head[v] = cnt++;

} inline void add2(int u, int v, ll w) , first[u] = cnt++;

edge[cnt] = (edge), first[v] = cnt++;

} int build(int l, int r)

void rebuild(int u, int ff)

void getroot(int u, int ff, int fe)

void dfs(int u, int ff, ll d)

void solve(int e)

void init()

void calc()

}int main()

WC2018 通道(邊分治套虛樹)

題目 先考慮兩棵樹怎麼做。我們在第二棵樹的每乙個點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考...

UOJ 349 WC2018 即時戰略

題目鏈結 一開始已知一號點。每次可以選定乙個已知點和乙個未知點,然後互動庫會返回從已知點出發到達未知點路徑上的第二個點。要求在有限步之內知道每乙個點。次數要求 鏈的情況要求 o n o n o n 其餘是 o n logn o nlogn o nlog n 首先是鏈的情況,記錄當前左右端點不斷往後探...

UOJ 348 WC2018 州區劃分

第一次知道子集卷積可以自己卷自己。這是一道子集卷積模板題。設 sum s 表示點集 s 的點權和。設 f s 表示對點集 s 進行州區劃分得到的答案,定義 g s 在點集 s 合法時為 sum s p 不合法時為 0 則 f s frac sum f t g s t 這東西是個子集卷積的形式。但是在...