洛谷 3806 模板 點分治1 點分治

2022-04-02 17:04:18 字數 1201 閱讀 9653

題目鏈結

題意: 給定一棵有n個點的樹,多次詢問樹上距離為k的點對是否存在。k<=1e7。

依舊點分治。注意到k的大小是可以開陣列的,對於所有出現的路徑長度用sum記錄下來,容斥去重時可以直接減掉。

但是如果像上面那樣記錄的話,複雜度是o(n^2)的。(資料弱還是能過)

注意到詢問只有100個,每次calc()可以對每個詢問更新答案,即對於每個詢問q[i]看是否有dep[q[i]-dep[j]]出現。

為了不讓當前點的同子樹的路徑重複更新答案,每次得到一棵子樹的d時,將其與之前子樹得到的d更新答案,更新完後再加入s。

注意初始s[0]=1(另外資料有0邊,所以應該是在每次計算前s[0]=1).

當然仍然可以用之前的方法做,不過是二分有多少條路徑長度等於q[j]-dep[i]。

#include #include #include #define gc() getchar()

//#define gc() (ss==tt&&(tt=(ss=in)+fread(in,1,maxin,stdin),ss==tt)?eof:*ss++)

const int n=10005,maxin=3e4;

int n,m,root,min,q[105],d[n],sz[n],enum,h[n],nxt[n<<1],to[n<<1],val[n<<1],q[n]/*清空狀態*//*,sum[10000003]*/;

bool vis[n],ans[105],s[10000003];

char in[maxin],*ss=in,*tt=in;

inline int read()

inline void addedge(int u,int v,int w)

void get_root(int x,int f,int tot)

mx=std::max(mx,tot-sz[x]);

if(mx=d[i]) ans[j]|=s[q[j]-d[i]];

for(int i=1; i<=d[0]; ++i) s[d[i]]=1,q[++q[0]]=d[i];

// for(int i=1; i// for(int j=i+1; j<=d[0]; ++j)

// sum[d[i]+d[j]]+=delta;

}void solve(int x)

int main()

洛谷 P3806 模板 點分治1 點分治

傳送門 點分治!點分治.滾,雖然也沒有可以講的扣就完事了理解好就行 這裡講一下自己計算答案時的乙個部分,我們設tti tt i tti 表示到當前重心的距離為i ii的路徑是否存在 對於每個詢問q iq i qi 因為我們便利完前面的i 1 i 1i 1棵子樹,所以用ttq i itt ttqi i...

洛谷P3806 模板 點分治1 點分治

感謝hzwer的點分治互測。給定一棵有n個點的樹 詢問樹上距離為k的點對是否存在。輸入格式 n,m 接下來n 1條邊a,b,c描述a到b有一條長度為c的路徑 接下來m行每行詢問乙個k 輸出格式 對於每個k每行輸出乙個答案,存在輸出 aye 否則輸出 nay 不包含引號 輸入樣例 1 複製2 1 1 ...

Luogu P3806點分治模板(點分治)

題目鏈結 wc聽不懂lca講的高等數學專場 乙個字都聽不懂 然後就自學了點分治。點分治就是我先處理完跟根有關的東西,然後把根標記掉,把原樹拆成若干個聯通塊,然後分別對每個聯通塊 每個小樹 搞一模一樣的操作。然後要每次求重心,因為點分治複雜度跟遞迴深度有關。本題判斷的時候偷懶用map,其實自己寫的sp...