每次找到樹的重心,分治下去統計答案(經過當前根節點的路徑)即可
統計答案使用了指標掃瞄陣列的方法,要注意去掉同一子樹內路徑的答案
還可以直接在樹上統計子樹答案(這個方法的好處是保證了分開的兩段路徑不在同一子樹內),但是要使用平衡樹,**複雜度高
#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,...