給定一棵有 n 個點的樹,詢問樹上距離為 k 的點對是否存在。
關於點分治具體內容可以看這個
這裡主要是詳細講講**:
getrt是用來求重心,我們利用樹型dp的思維來做,即找到該節點所有的子樹,找到最大的哪一顆即可
void
getrt
(int u,
int pa)
//求重心
maxp[u]
=max
(maxp[u]
,sum-size[u]);
if(maxp[u]
) rt=u;
}
getdis是用來求每乙個子節點到根的距離
getdis在calc中不斷被呼叫
void
getdis
(int u,
int fa)
//每乙個子節點到根的距離
}
calc是用來合併答案的,因為在getdis中已經計算出所有點到根的距離,所以把任意兩個出現的距離湊在一起,並】、判斷可否湊出我們需要的k即可
rem[i]存的是在getdis中求出的距離,rem[0]這個值是值rem存了多少值
judge我們可以用來存距離,對已經出現的距離用judge標記為1,這樣當出現另乙個距離可以和這個距離搭配成我們所需的k時,就可以直接標記答案
judge[query[k]-rem[j]];
query[k]-rem[j]即為所需要的距離
test[k]|=judge[query[k]-rem[j]];
用|就可以實現如果有就給test標記
void
calc
(int u)
for(
int j=rem[0]
;j;--j)
//儲存出現過的dis於judge
}for
(int i=
1;i<=p;
++i)
//處理完這個子樹就清空judge
judge[q[i]]=
0;//特別注意一定不要用memeset,會t
}
solve則是對每乙個根進行處理,通過solve來呼叫上述函式,在遞迴過程中不斷重複一樣的過程
void
solve
(int u)
}
//niiick
#include
#include
#include
#include
#include
#include
using
namespace std;
intread()
while
(ss>=
'0'&&ss<=
'9')
return f*x;
}const
int inf=
10000000
;const
int maxn=
100010
;int n,m;
struct
node
e[maxn<<1]
;int tot,head[maxn]
;int maxp[maxn]
,size[maxn]
,dis[maxn]
,rem[maxn]
;int vis[maxn]
,test[inf]
,judge[inf]
,q[maxn]
;int query[
1010];
int sum,rt;
int ans;
void
add(
int u,
int v,
int dis)
void
getrt
(int u,
int pa)
//求重心
maxp[u]
=max
(maxp[u]
,sum-size[u]);
if(maxp[u]
) rt=u;
}void
getdis
(int u,
int fa)
//每乙個子節點到根的距離
}void
calc
(int u)
for(
int j=rem[0]
;j;--j)
//儲存出現過的dis於judge
}for
(int i=
1;i<=p;
++i)
//處理完這個子樹就清空judge
judge[q[i]]=
0;//特別注意一定不要用memeset,會t
}void
solve
(int u)
}int
main()
for(
int i=
1;i<=m;
++i)
query[i]
=read()
;//先記錄每個詢問以離線處理
maxp[rt]
=sum=n;
//第一次先找整棵樹的重心
getrt(1
,0);
solve
(rt)
;//對樹進行點分治
for(
int i=
1;i<=m;
++i)
return0;
}
//#pragma optimize("ofast")
#include
#define
maxn
10005
#define
maxk
10000007
#define
infint
(16843009
)using
namespace std;
typedef
long
long ll;
int n,m,k[maxn]
;struct
edge};
vector adj[maxn]
;int vis[maxn]
,d[maxn]
,sz[maxn]
;int rt,cnt;
void
dfs_rt
(int u,
int fa,
int tot)
n =max(n, tot-sz[u]);
if(2*n <= tot) rt = u;
}bool t[maxk]
, ans[maxn]
;void
dfs1
(int u,
int fa)
int v,w;
for(
int k=
0;k.size()
;k++)}
void
dfs2
(int u,
int fa,
int flag)
}int v;
for(
int k=
0;k.size()
;k++)}
void
work
(int u,
int fa,
int tot)
dfs2
(u,0,-
1);for
(int k=
0;k.size()
;k++)}
intmain()
for(
int i=
1;i<=m;i++
) t[0]
=1;work(1
,0,n);
for(
int i=
1;i<=m;i++
)return0;
}
P3806 模板 點分治1
感謝hzwer的點分治互測。給定一棵有n個點的樹 詢問樹上距離為k的點對是否存在。輸入格式 n,m 接下來n 1條邊a,b,c描述a到b有一條長度為c的路徑 接下來m行每行詢問乙個k 輸出格式 對於每個k每行輸出乙個答案,存在輸出 aye 否則輸出 nay 不包含引號 輸入樣例 1 複製2 1 1 ...
P3806 模板 點分治1
感謝hzwer的點分治互測。給定一棵有n個點的樹 詢問樹上距離為k的點對是否存在。輸入格式 n,m接下來n 1條邊a,b,c描述a到b有一條長度為c的路徑 接下來m行每行詢問乙個k 輸出格式 對於每個k每行輸出乙個答案,存在輸出 aye 否則輸出 nay 不包含引號 輸入樣例 1 2 1 1 2 2...
P3806 模板 點分治1
p3806 模板 點分治1 定一棵有 n 個點的樹,多次詢問樹上距離為 k 的點對是否存在。澱粉質模板題。澱粉質的核心就是其只統計經過當前根結點的路徑,即可以把兩條路徑 拼 起來,同時分治結構保證了其只有 log 次這樣的計算。常用於統計樹上點對數量這樣的問題。來看這道題。可以對每乙個路徑長度開乙個...