P3806 模板 點分治1

2021-10-25 02:55:44 字數 4005 閱讀 4155

給定一棵有 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 次這樣的計算。常用於統計樹上點對數量這樣的問題。來看這道題。可以對每乙個路徑長度開乙個...