BZOJ2870 最長道路Tree(邊分治)

2021-09-20 18:47:27 字數 1656 閱讀 3944

傳送門

邊分治比點分治好的一點就是每次分出來都只有2個集合

如果遇到難以合併的資訊的時候邊分治就很有用了

手動轉二叉樹

每次可以按照權值大小排序後對兩個集合雙指標掃兩遍

具體實現可以看**

複雜度o(n

log2

n)

o(nlog^2n)

o(nlog

2n)

#include

using

namespace std;

const

int rlen=

1<<20|

1;#define ll long long

#define pb push_back

#define pii pair

#define gc getchar

inline

intread()

const

int n=

200005

;const

int inf=

1e9;

int n,pn,mx,mxsiz,tot,rt;

ll ans;

int adj[n]

,nxt[n<<1]

,to[n<<1]

,siz[n]

,val[n<<1]

,vis[n<<1]

,cnt=

1,pt[2]

,a[n]

;pii tmp[2]

[n];

#define fi first

#define se second

inline

bool

comp

(const pii &a,

const pii &b)

vector<

int> son[n]

;inline

void

addedge

(int u,

int v,

int w)

void

dfs(

int u,

int f)

}inline

void

rebuild()

}else}}

}inline

void

getrt

(int u,

int f)

}void

getdis

(int kd,

int u,

int f,

int dep,

int va)

}void

solve

(int u,

int sz)

for(

int i=

1,j=

1,mxl=

0;i<=pt[1]

;i++

)int ksz=siz[to[now]];

solve

(to[now]

,ksz)

,solve

(to[now^1]

,sz-ksz);}

intmain()

dfs(1,

0),rebuild()

,solve(1

,n);

cout<}

BZOJ2870 最長道路

許可權題 給出一棵樹,點有點權,找到樹上的一條路徑使得路徑上點的個數和其中點權最小的點的點權之積最大,輸出最大值。邊分治板子題啦。邊分治後對於分出來的兩棵子樹 按到左右根的最小點權排序後直接用單調指針對每乙個點找到另一棵樹中的最優點即可。code include using namespace st...

bzoj 2870 最長道路tree

題目 邊分治邊分和點分相比就是找到一條重心邊,考慮所有經過這條邊的路徑,之後斷開這條邊分成兩個聯通塊,繼續分治 由於每次分治重心是一條邊,所以只會產生兩個聯通塊,考慮兩個聯通塊顯然要比像點分那樣考慮多個聯通塊容易 但是邊分有乙個問題,就是遇到菊花圖就自閉了,複雜度變成了 o n 2 我們注意到邊分的...

BZOJ2870 最長道路tree

題解 子樹分治的做法可以戳這裡 可是碼量。這裡介紹另一種好寫又快的方法。我們還是一顆一顆子樹處理,處理完乙個子樹,考慮列舉最小值。如果我們現在處理到了x節點,它到根的min為w。那麼我們就可以在以前的資訊中找出min w且長度最長的一條鏈並且用它和該鏈合併,同時更新答案。這個顯然可以用樹狀陣列搞。處...