https://ac.nowcoder.com/acm/contest/6944/B
題名
ポイントウェイトを含む、ルートが1のルート付きツリーモデル。
各ノードuについて、サブツリーは任意LCA(i,j)
にuの2点であり、最大のものを見つけ、GCD(i,j)
最大の場合のij
解の数を求めます。
アイデア
- このトピックの重みのスコープはnと同じであることに注意してください。
- すべての数値はそれらの要素を列挙します。これらの要素はセットに配置され、サイズは最大データ範囲を超えません。
- 実際、統計gcdは本質的に統計的要因です。
- 構造を使用して、サブツリーのすべての数を分解した後、因子の数をカウントします。
- 計算ノードへの答えは、いくつかの再帰的な蓄積です。
- ヒューリスティックなマージの最適化を考えると、複雑さはほとんど同じです。
- O(N(ai + log(N)))O(N(\ sqrt {a_i} + log(N))) O (N (a私+l o g (N )))
非常に優れたヒューリスティックな複合練習問題。
参照コード
vector<int> g[MAXN];
map<ll, ll> p[MAXN];
ll val[MAXN];
ll cnt[MAXN];
void dfs(int u, int f) {
for (auto v: g[u]) {
if (v == f) continue;
dfs(v, u);
if (p[u].size() < p[v].size()) {
p[u].swap(p[v]);
}
for (auto pi : p[v]) {
int x = pi.first;
if (p[u].count(x) == 0) {
p[u].emplace(pi);
continue;
}
if (x > val[u]) {
val[u] = x;
cnt[u] = p[u][x] * p[v][x];
} else if (x == val[u]) {
cnt[u] += p[u][x] * p[v][x];
}
p[u][x] += p[v][x];
}
}
// debug(u, p[u]);
}
void solve(int kaseId = -1) {
int n;
cin >> n;
for (int i = 2, u, v; i <= n; ++i) {
cin >> u >> v;
g[u].emplace_back(v);
g[v].emplace_back(u);
}
for (ll i = 1, ai; i <= n; ++i) {
cin >> ai;
for (ll j = 1; j * j <= ai; ++j) {
if (ai % j == 0) {
p[i].emplace(j, 1);
p[i].emplace(ai / j, 1);
}
}
}
dfs(1, -1);
for (int i = 1; i <= n; ++i) {
cout << val[i] << " " << cnt[i] << endl;
}
}