AcWing 252 樹 點分治

2022-07-15 09:42:11 字數 1379 閱讀 2038

每次找到樹的重心,分治下去統計答案(經過當前根節點的路徑)即可

統計答案使用了指標掃瞄陣列的方法,要注意去掉同一子樹內路徑的答案

還可以直接在樹上統計子樹答案(這個方法的好處是保證了分開的兩段路徑不在同一子樹內),但是要使用平衡樹,**複雜度高

#include#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

const int maxn = 200010;

const int inf = 1000000007;

int n, k;

int mx, tot, root, ans, tail;

struct node

}a[maxn];

void add_node(int u, int bel, int dis)

int h[maxn], cnt;

structe[maxn << 1];

void add(int u, int v, int w)

int sz[maxn], son[maxn], dis[maxn], vis[maxn];

int c[maxn]; // c[i] :屬於 i 子樹的節點有多少個

void get_root(int u, int par)

son[u] = max(son[u], tot - son[u]);

if(mx > son[u])

}void get_dis(int u, int par, int rt)

}void calc(int u)

sort(a + 1, a + 1 + tail); // 將子樹節點按距離排序

for(int i = 1; i <= tail ; ++i ) ++c[a[i].bel]; // 統計每個子樹內節點的數量

// 統計答案

int head;

for(head = 1; head < tail ; ++head)

ans += tail - head - c[a[head].bel];

} for(int i = head; i <= tail ; ++i ) --c[a[i].bel];

}void fenzhi(int u)

}ll read() while(ch>='0' && ch<='9') return s*f; }

int main()

mx = inf, tot = n;

get_root(1, 0);

fenzhi(root);

printf("%d\n",ans); }

return 0;

}

AcWing252 樹(點分治)

本題如果k的範圍較小的話,可以使用樹狀陣列記錄答案,但是因為很大 考慮使用雙指標 容斥原理。也就是直接算整個子樹的答案,之後再在列舉兒子節點的時候,把加上u v這條邊的合法答案全部清除,這樣就做到了不重不漏 includeusing namespace std typedef long long l...

AcWing252 樹 (點分治模板題)

傳送門 做一道點分治的裸題 這個題要求一顆樹上路徑長度小於等於 k 的路徑的數量。可以用樹狀陣列維護子樹到重心距離在 0,k dis 的節點數量。但樹狀陣列沒法維護 0 的資訊,就同意偏移 1 include define lowbit x x x using namespace std const...

點分治(樹分治)

將原問題分解成若干相同形式,相互獨立的子問題,各個擊破 一般用來解決有關樹上路徑的統計和詢問 p4178 tree 給定一棵 n 個節點的樹,每條邊有邊權,求出樹上兩點距離小於等於 k 的點對數量。暴力做法 o n2 點分治做法 選擇乙個點作為分治中心,令其為rt做dfs。對於一條路徑path u,...