點分治的入門練習。
題目鏈結
bzoj的鏈結
(許可權題)
關於點分治的思想我就不再重複了,這裡重點說一下如何判重。
我們來看上圖,假設我們去除了1節點,求出d[2]=1,d[3]=d[4]=2
假設k為5,這樣我們會認為節點(2,3)(2,4)(3,4)的距離小於k,從而累計到答案中
但是我們以2為root做點分治時還會將(3,4)計算一遍,這樣就重複了
所以我們每一次計算答案時還要講所有多餘情況減去,最終答案才是我們要求的答案
不難發現多餘情況是在root節點與root子節點重複統計的,我們在點分治時將所有root子節點的答案減去就好了
# include# include# include
# include
# include
using
namespace
std;
const
int mn = 40005
;struct edge;
edge e[mn*2
];int
head[mn],edge_max;
void add(int x,int y,int
z)bool
vis[mn];
intn,k,ans;
intmx[mn],siz[mn],root,sum;
intd[mn],deep[mn];
void getroot(int x,int
fa) mx[x]=max(mx[x],sum-siz[x]);
if(mx[root]>mx[x])
root=x;
}void getdeep(int x,int
fa)}
int cal(int x,int
now)
else r--;
}returnt;}
void solve(intx)}
intmain()
scanf("%d
",&k);
mx[0]=1
<<30,sum=n;
getroot(
1,0);
solve(root);
printf(
"%d\n
",ans);
return0;
}
洛谷P4178 Tree 分塊
給你一棵樹,以及這棵樹上邊的距離,問有多少對點它們兩者間的距離小於等於kkk。這道題是應該加強資料了。當然如果這道題不打算做點分治模板題的話可以不用 o n nlog n o n sqrt n log sqrt n o nn logn 分塊在洛谷優秀的o2o2 o2下過了。我們假設1 11為樹根,d...
洛谷P4178 Tree(點分治)
考慮點分治,對於乙個子樹,求出每個點到根的距離並排序,用雙指標掃瞄,但這樣會把來自同乙個兒子的路徑也統計上去,再對每個兒子做一遍,減去即可。include include include include using namespace std typedef long long ll const i...
洛谷p4178 點分治 線段樹
這道題目是點分治的題目,與模板題不一樣的是,這是要統計小於路徑長度為k的點對數。我們分析下與模板題的區別,模板要求的是路徑等於k的長度的路徑是否存在,然後統計的方法是對於每個重心 跟 求出各點與根的路徑,然後重心下面的各個子樹中,相同的子樹不去統計答案,去計算之前非該子樹的路徑能否湊出k的路徑,也就...