P3806 模板 點分治1

2022-05-15 23:57:43 字數 1823 閱讀 5417

感謝hzwer的點分治互測。

給定一棵有n個點的樹

詢問樹上距離為k的點對是否存在。

輸入格式:

n,m接下來n-1條邊a,b,c描述a到b有一條長度為c的路徑

接下來m行每行詢問乙個k

輸出格式:

對於每個k每行輸出乙個答案,存在輸出「aye」,否則輸出」nay」(不包含引號)

輸入樣例#1:

2 1

1 2 2

2

輸出樣例#1:

aye
對於30%的資料n<=100

對於60%的資料n<=1000,m<=50

對於100%的資料n<=10000,m<=100,c<=10000,k<=10000000

對於每個點,分為有長度為k的路徑經過點以及長度為k的路徑在其子樹

對於長度為k的路徑在其子樹的點,我們可以將其看作是長度為k的路徑經過其子樹所在根節點

那麼這就是點分治的基本思想

為降低複雜度,我們每次採取重心作為根節點。將樹的深度將至logn

則複雜度為o(nlogn2)

#include#define inf 0x3f3f3f3f

using

namespace

std;

const

int maxn=10000+100,maxm=10000000+100

;int

head[maxn];

intq[maxn],ans[maxn];

intp[maxm],t[maxn];

intd[maxn],dis[maxn],vis[maxn];

ints[maxn],ms[maxn];

int rt=0

,sum;

intn,m;

struct

edge

e[maxn

<<1

];int size=0

;inline

intread()

while(ch>='

0'&&ch<='9')

return x*f;

}void addedge(int u,int v,int

w)void tc(int u,int fa)//

樹的重心

ms[u]=max(ms[u],sum-ms[u]);

if(ms[u]u;

}void dfs(int u,int

fa)}

void cal(int

u)

for(int i=1;i<=tot;i++)

p[t[i]]=0;//

桶清空,用memsettle

}void solve(intu)}

intmain()

for(int i=1;i<=m;i++)

q[i]=read();

sum=n;ms[rt]=inf;

tc(1,0);

solve(rt);

for(int i=1;i<=m;i++)

puts(ans[i]?"

aye":"

nay"

);

return0;

}

view code

P3806 模板 點分治1

給定一棵有 n 個點的樹,詢問樹上距離為 k 的點對是否存在。關於點分治具體內容可以看這個 這裡主要是詳細講講 getrt是用來求重心,我們利用樹型dp的思維來做,即找到該節點所有的子樹,找到最大的哪一顆即可 void getrt int u,int pa 求重心 maxp u max maxp u...

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

p3806 模板 點分治1 定一棵有 n 個點的樹,多次詢問樹上距離為 k 的點對是否存在。澱粉質模板題。澱粉質的核心就是其只統計經過當前根結點的路徑,即可以把兩條路徑 拼 起來,同時分治結構保證了其只有 log 次這樣的計算。常用於統計樹上點對數量這樣的問題。來看這道題。可以對每乙個路徑長度開乙個...