luogu P3806 模板 點分治1

2021-10-19 21:17:09 字數 2297 閱讀 2332

給你一棵樹,路徑有長度,多次詢問,每次給出 k,問你是否存在路徑長度為 k 的點對。

這道題我們用分治的方法。

那我們假設要解決乙個樹,那我們先選重心作為根節點(為了減少高度節省時間)。

然後就分成兩種討論,一種是路徑都在同乙個子樹中,那這個我們就可以把問題轉換為解決這個子樹。

另一種就是在兩個不同的子樹中(或者乙個是根節點)。那我們考慮直接搜出點到根節點的距離,然後任意兩個相加都是一種可行的 k

kk。(因為都是在不同子樹,或者是乙個是根節點的話距離就是另乙個到根節點的距離,所以是可以直接相加的)

首先,它可能是根節點,那它到根節點的距離就是 0

00,那乙個的距離為 0

00 就是存在的。

然後你考慮枚舉子樹,然後求出每個點到根節點的距離。然後我們這樣弄:我們列舉每個點和你給出的詢問(也就是離線弄)的 y

yy,那首先,這個點到根節點的距離 x

xx 一定是要小於等於 y

yy 的,然後如果要使得這個詢問的結果是有,那距離為 y−x

y-xy−

x 的點是一定要存在的,因為這樣就可以通過這兩個,得出 y

yy 的距離。

那你為了不會找到的點跟它是同乙個子樹中的,你就可以進行完上面的操作,才把你這個子樹的距離都標記為存在。

然後你每次不同的根統計那個存在的距離都是不同的,那你就要把之前的清空。

但是不能用 memset,因為陣列太大會超時。

但其實它真正有值的不多,那我們可以每次標記的時候把標記的點用乙個佇列記錄下來(棧也行,反正就是拿個陣列記錄值為 1

11 的位置),然後你要清空的時候就列舉這些值為 1

11 的地方,把它們賦值為 0

00 即可。

然後加個快讀什麼的就可以了。

#include

#include

#include

#include

#include

using

namespace std;

struct node e[

200001];

struct tree t[

100001];

int n, m, x, y, z, le[

100001

], kk;

bool in[

100001

], answer[

101]

;int ans[

10000001

], rem[

101]

, que[

10000001];

int d[

100001

], dis[

100001

], root;

int k, fa[

100001

], s, maxn[

100001];

intread()

while

(c >=

'0'&& c <=

'9')

return re;

}bool

cmp(

int x,

int y)

void

add(

int x,

int y,

int z)

; le[x]

= kk;

}void

find_root

(int now,

int father)

maxn[now]

=max

(maxn[now]

, s - t[now]

.s);

if(maxn[now]

< maxn[root])}

void

get_dis

(int now,

int father)

}void

count_

(int now)

}while

(que[0]

)}void

dfs(

int now)

}int

main()

for(

int i =

1; i <= m; i++)

s = n;

maxn[0]

= n;

root =0;

find_root(1

,0);

dfs(root)

;for

(int i =

1; i <= m; i++

)return0;

}

luogu P3806 模板 點分治1

題目描述 給定一棵有n個點的樹 詢問樹上距離為k的點對是否存在。多次詢問 可離線 我們先隨意指定乙個虛擬根root,將這棵樹轉化成無根樹 樹上的路徑可以分為兩類,1.經過根節點u的路徑 2.完全在u子樹裡 不經過u 的 對於1,用dis表示當前結點到根節點root的路徑長度,則root的子樹中兩個節...

Luogu P3806 模板 點分治1

給定一棵有 n nn 個點,邊權的樹,回答 m mm 個詢問,每次詢問樹上距離為 k kk 的點對是否存在。資料範圍n 1 04,m 100,邊權 10000,k 107 n leqslant 10 4,m leqslant 100,texttt leqslant 10000,k leqslant ...

luogu P3806 模板 點分治1

給你一棵樹,路徑有長度,多次詢問,每次給出 k,問你是否存在路徑長度為 k 的點對。這道題我們用分治的方法。那我們假設要解決乙個樹,那我們先選重心作為根節點 為了減少高度節省時間 然後就分成兩種討論,一種是路徑都在同乙個子樹中,那這個我們就可以把問題轉換為解決這個子樹。另一種就是在兩個不同的子樹中 ...