許可權題
給出一棵樹,點有點權,找到樹上的一條路徑使得路徑上點的個數和其中點權最小的點的點權之積最大,輸出最大值。
邊分治板子題啦。
邊分治後對於分出來的兩棵子樹 , 按到左右根的最小點權排序後直接用單調指針對每乙個點找到另一棵樹中的最優點即可。
code:
#include
using
namespace std;
#define set(a,b) memset(a,b,sizeof(a))
template
<
class
t>
inline
void
init
(t&x)
int n,n;
typedef
long
long ll;
typedef vector<
int> ary;
const
int maxn=
2e5+10;
// 4 倍空間 , 類似線段樹
int val[maxn]
;ary son[maxn]
;struct edgea[maxn<<1]
;int head[maxn]
,cnt=0;
inline
void
add(
int x,
int y,
int z)
;head[x]
=cnt++;}
inline
void
add_edge
(int x,
int y,
int z)
void
dfs(
int u,
int fa)
inline
void
rebuild()
}else
}return;}
int vis[maxn]
;int mx,size[maxn]
,ced,sz;
ll ans;
void
find
(int u,
int fa)
return;}
typedef pair<
int,
int> pa;
pa s[2]
[maxn]
;int top[2]
;void
dfs(
int u,
int fa,pa*s,
int&top,
int dis,
int mi)
return;}
void
divide
(int u)
p=top[0]
;maxlen=0;
for(
int i=top[1]
;i;--i)
int sl=a[ced]
.to,sr=a[ced^1]
.to;
int tot=sz,szl=size[sl]
; sz=szl;
divide
(sl)
; sz=tot-szl;
divide
(sr)
;return;}
intmain()
dfs(1,
0);rebuild()
;sz=n;ced=0;
divide(1
);cout
}
bzoj 2870 最長道路tree
題目 邊分治邊分和點分相比就是找到一條重心邊,考慮所有經過這條邊的路徑,之後斷開這條邊分成兩個聯通塊,繼續分治 由於每次分治重心是一條邊,所以只會產生兩個聯通塊,考慮兩個聯通塊顯然要比像點分那樣考慮多個聯通塊容易 但是邊分有乙個問題,就是遇到菊花圖就自閉了,複雜度變成了 o n 2 我們注意到邊分的...
BZOJ2870 最長道路tree
題解 子樹分治的做法可以戳這裡 可是碼量。這裡介紹另一種好寫又快的方法。我們還是一顆一顆子樹處理,處理完乙個子樹,考慮列舉最小值。如果我們現在處理到了x節點,它到根的min為w。那麼我們就可以在以前的資訊中找出min w且長度最長的一條鏈並且用它和該鏈合併,同時更新答案。這個顯然可以用樹狀陣列搞。處...
BZOJ2870 最長道路Tree(邊分治)
傳送門 邊分治比點分治好的一點就是每次分出來都只有2個集合 如果遇到難以合併的資訊的時候邊分治就很有用了 手動轉二叉樹 每次可以按照權值大小排序後對兩個集合雙指標掃兩遍 具體實現可以看 複雜度o n log2 n o nlog 2n o nlog 2n include using namespace...