求一棵樹上有多少條路徑長度≤le
n\leq len
≤len
首先普通點分治。掃瞄的時候將每個點儲存為乙個二元組(di
s,gr
a)
(dis,gra)
(dis,g
ra)分別表示離(分治到的)根的距離,屬於根的那顆子樹。
然後按照dis
disdi
s排序,兩個指標l,r
l,rl,
r用cn
icn_i
cni
表示[ l+
1,r]
[l+1,r]
[l+1,r
]這個區間內是i
ii這個子樹的點的個數。
然後我們發現滿足dis
l+di
sr≤l
en
dis_l+dis_r\leq len
disl+
disr
≤le
n這個範圍根據l
ll的向前r
rr是單調不公升的然後兩個指標維護一下每次統計一下答案r−l
−cnl
r-l-cn_l
r−l−cn
l
#include
#include
#include
using
namespace std;
const
int n=
100100
;struct nodea[n*3]
;struct num_nodenum[n]
;int siz[n]
,ls[n]
,v[n]
,root,len,n,f[n]
,ans,tot,x,y,w,cnt,cn[n]
;bool
cmp(num_node x,num_node y)
void
addl
(int x,
int y,
int w)
void
groot
(int x,
int fa)
f[x]
=max
(f[x]
,n-siz[x]);
if(f[x]
) root=x;
}void
dfs(
int x,
int fa,
int w,
int grafa)
voiddp(
int x)
for(
int i=ls[x]
;i;i=a[i]
.next)if(
!v[a[i]
.to])}
intmain()
f[0]=
2147483647
;groot(1
,0);
dp(root)
;printf
("%d"
,ans)
;}
JZOJ 1166 樹中點對距離
給出一棵帶邊權的樹,問有多少對點的距離 le n 2 n 10000 len 231 這是一道十分經典的點分治題目。點分治,顧名思義,就是按照點來分治。假設當前要計算某棵子樹裡面滿足題目條件的點對數,我們可以先找出這棵子樹的重心。易知,此棵子樹的點對數 經過重心的合法點對數 不經過重心的合法點對數。...
樹中點對距離(點分治)
給出一棵帶邊權的樹,問有多少對點的距離 len 這是一道點分治的經典題目,可以給點分治的初學者練手。點分治,顧名思義就是把每個點分開了處理答案。假設,目前做到了以x為根的子樹。先求出子樹中每個點到根的距離di s 對於兩個點 i 和 j,如果di si d isj k 那麼 i j 就是乙個合法的點...
樹中點對距離
在一顆n個結點的樹上,統計有多少點對最短距離 m。點對不存在順序性 n 10000 我們選取乙個點x作根,那麼任何點對都分成兩種型別 1 經過x 2 不經過x 我們對經過x的進行統計,對於不經過x的繼續在x的子樹中分治下去。這就是點分治。我們處理出每個點的深度,排序後就很容易統計經過x的個數。不過有...