bzoj3784 樹上的路徑(二分答案 點分治)

2021-09-10 01:50:20 字數 2082 閱讀 4437

傳送門

點分治好題。

題意簡述:給一棵帶邊權的樹,問所有路徑中前m

mm大的。m

≤300000

m\le300000

m≤3000

00思路:

網上有題解寫了可以通過什麼點分治序轉化成超級鋼琴那道題的做法蒟蒻嚇得瑟瑟發抖。

然後由於我比較菜想了乙個二分答案的方法。

我們二分第m

mm大的值,每次用點分治檢驗合法性。

二分完了之後我們再跑一次點分統計答案。

然後第乙個二分的時候直接做是log

n3

log^3_n

logn3​

的。考慮降下來乙個log

loglo

g。我們先dfs

dfsdf

s一次樹把每個點作為重心的時候的所有dis

tdist

dist

預處理下來就可以省掉乙個log

loglo

g啦! 空間複雜度o(nlogn)233

**:

#include

#define ri register int

#define fi first

#define se second

using

namespace std;

inline

intread()

typedef

long

long ll;

typedef pair<

int,

int> pii;

const

int n=

5e4+

5,m=

3e5+5;

int n,m,siz[n]

,msiz[n]

,stk[m]

,top=

0,rt,all,rt;

bool vis[n]

;vectore[n]

;vector<

int>dis[n]

,g[n]

,inv[n]

;ll ans;

priority_queue<

int>ans;

void

getroot

(int p,

int fa)

msiz[p]

=max

(msiz[p]

,all-siz[p]);

if(msiz[p]

)rt=p;

}void

solve

(int p,

int fa,

int dist,vector<

int>

&anc)

}void

dfs(

int p)

}inline ll calc

(vector<

int>

&v,int lim)

void

dfs(

int p,

int lim)

inline

bool

check

(int mid)

void

dfs(

int p,

int fa,

int dist)

inline

void

solve

(int p,

int lim)

sort

(stk+len+

1,stk+top+1)

,inplace_merge

(stk+

1,stk+len+

1,stk+top+1)

;}}inline

void

ask(

int p,

int lim)

intmain()

memset

(vis,0,

sizeof

(vis)),

ask(rt,k)

;for

(ri i=

1;i<=m;

++i)

return0;

}

bzoj3784 樹上的路徑

time limit 10 sec memory limit 256 mb submit 789 solved 266 submit status discuss 給定乙個n個結點的樹,結點用正整數1.n編號。每條邊有乙個正整數權值。用d a,b 表示從結點a到結點b路邊上經過邊的權值。其中要求a ...

BZOJ3784 樹上的路徑

樹的點分治,在分治的時候將所有點到根的距離依次放入乙個陣列q中。對於一棵子樹裡的點,合法的路徑一定是q l q r 的某個數加上自己到重心的距離。定義五元組 v,l,m,r,w 表示當前路徑長度為v,在 l,r 裡選出最大值m,並加上w。用大根堆維護這些五元組,每次取出v最大的元素,並擴充套件出 l...

BZOJ3784樹上的路徑

題目描述 給定乙個n個結點的樹,結點用正整數1.n編號。每條邊有乙個正整數權值。用d a,b 表示從結點a到結點b路邊上經過邊的權值。其中要求a題解 把每次點分治時的dfs序寫下來,假設我們在乙個位置找能夠和它拼成一條鏈的另乙個位置,可以發現那些位置的順序在dfs序上構成了一段連續區間,用st表 堆...