模板 點分治1

2022-02-27 06:10:11 字數 1831 閱讀 5609

感謝hzwer的點分治互測。

給定一棵有n個點的樹

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

輸入格式:

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

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

輸出格式:

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

點分治裸題。。。

一種優化的暴力,可以方便的求出樹上兩點間的距離

我們知道,樹的重心可以使樹的深度最小(最壞n/2,期望logn)

我們在點分治時就可以這麼來優化

每次找到樹的重心,然後遍歷子樹,dfs計算出每一條經過重心的路徑長度

然後刪掉重心,每個新形成的樹再跑一遍

直到無法遞迴為止

長度記下來,o(1)查詢即可

#include#include

#include

#define rii register int i

#define rij register int j

using

namespace

std;

bool bj[10000005

];struct

ljbx[

20005

];int sd,lsl,cnt,head[10005],last[10005

],ans,n,m,k;

int cd[10005],ks[10005],js[10005],zg[10005],size[10005

];int judge[10005

];void dfs1(int wz,int fa,int

sd) dfs1(x[ltt].to,wz,sd+x[ltt].val);

ltt=x[ltt].next;

}return;}

int dfs(int wz,int

fa) ltt=x[ltt].next;

}if(size[wz]*2>=n&&!ans)

return0;

}void updata(int l,int

r) }

return;}

void solve(int

wz)

int ltt=head[zx];

while(ltt!=0

)

ltt=x[ltt].next;

}for(rii=1;i<=lsl;i++)

}for(rii=1;i<=cnt;i++)

zg[zx]=1

; ltt=head[wz];

while(ltt!=0

)

ltt=x[ltt].next;

}return;}

intmain()

x[i*2-1].to=kkk;

x[i*2-1].val=val;

if(last[ltt]!=0

)

last[ltt]=i*2-1

;

if(head[kkk]==0

)

x[i*2].to=ltt;

x[i*2].val=val;

if(last[kkk]!=0

)

last[kkk]=i*2

; bj[val]=1

; }

solve(1);

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

else

}}

點分治 模板 1

自己整理模板,僅作模板儲存使用 樹上點分治模板 1 該模板有一巨大bug 在統計路徑長度為單邊長度時,會出錯 include include include include using namespace std define inf 999999999 int n,m,len 0,size str...

點分治模板

luogu 3806 近些日子學了點分治,當然只是學了個模板。所謂點分治,使用於處理樹上路徑的一種分治手段。因為利用了重心的性質,時間複雜度可以保證呢。所謂演算法流程 選取當前子樹的重心 計算路徑總數,不管路徑是否過當前重心 後面會去重 計算起點和終點在同一顆子樹中的合法路徑 因為這條路徑不是簡單路...

點分治模板

這兩天跟著學了一手樹上點分治模板,然後有一些感悟,決定來寫一發部落格.首先,鑑於鄙人的經驗,如果想要較快速地學習乙個新演算法,肯定還是先看一道經典的例題比較好,所以我們先來一道例題.給你一棵tree,以及這棵樹上邊的距離.問有多少對點它們兩者間的距離小於等於k 輸入格式 n n 40000 接下來n...