樹中點對距離(點分治)

2021-07-13 13:25:59 字數 1494 閱讀 7908

給出一棵帶邊權的樹,問有多少對點的距離<=len

這是一道點分治的經典題目,可以給點分治的初學者練手。

點分治,顧名思義就是把每個點分開了處理答案。

假設,目前做到了以x為根的子樹。

先求出子樹中每個點到根的距離di

s ,對於兩個點

i 和

j,如果di

si+d

isj<=

k ,那麼(i

,j) 就是乙個合法的點對。

而點對的路徑就會有兩種:經過x點的和不經過x點的。

顯然,不經過x點的一定會再x的兒子的子樹中被計算過。所以,我們要減去不經過x點的。

那怎麼把不經過x點的減去呢?

用以x為根的子樹的di

s 值(why?如果用以x的兒子為根的子樹的di

s ,就會有些可以到達x的兒子的卻不能到達x的點對,被多減掉),來計算以x的兒子為根的子樹中的點對數量,用減去它們就可以了。

記住要找重心

#include 

#include

#include

#include

#include

#include

#include

const

long

long maxlongint=2147483647;

using

namespace

std;

long

long dis[12000],next[22000],last[20020],to[20200],n,m,tot,v[20200],d[5000],sum=0,size[20020],mx[20020],f,root,ans;

bool bz[20020];

long

long bj(long

long x,long

long y,long

long z)

void findroot(long

long x,long

long fa)

}mx[x]=max(mx[x],f-size[x]);

if (mx[x]return;

}void q(long

long l,long

long r)

}if(iif(llong

long dg1(long

long x,long

long fa)

}}long

long getsum()

}return y;

}long

long dg(long

long x,long

long fa)

}}int main()

mx[0]=maxlongint;

f=n;

findroot(1,0);

dg(root,0);

printf("%lld\n",ans);

}

點分治模板 (樹中點對距離)

點分治就是在一棵樹中,將每個點分治 基本概念 點分治 將一棵無根樹變成有根樹,再分別處理每棵有根子樹。重心 在一棵樹中,這個點的最大子樹是所有點中最小的。也可以說是刪除該點時,樹內剩下的子樹最大節點數最小。size i 表示以i為根的子樹節點數量。如何求重心?求出size,什麼是定義,就怎麼求。一般...

點分治入門 樹中點對距離詳(?)解

其中樹最多有10000個點,len maxlongint 這是一道模板題目。對於乙個點x,我們考慮如何求解經過x點的路徑方案數,設為f x 考慮直接從x出發做一遍dfs,算出所有未到過的點到x點的距離,然後排序。設兩個指標,如果length l length r len,那麼length l len...

jzoj1166 樹中點對距離 點分治

求一棵樹上有多少條路徑長度 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...