傳送門
點分治好題。
題意簡述:給一棵帶邊權的樹,問所有路徑中前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表 堆...