Niuke Challenge 42Bヒューリスティックマージ

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;
    }
}

おすすめ

転載: blog.csdn.net/Tighway/article/details/108446267