1 条题解

  • 0
    @ 2026-10-26 22:20:37

    思路与算法

    迭代后序计算普通结构和镜像结构的规范ID;三元组(点权,左ID,右ID)精确驻留,相等键才共用ID,哈希槽碰撞会继续探测而不误判。

    按上述模型建立状态或枚举对象,依代码中的顺序处理输入并输出完整答案。

    正确性说明

    对叶子及每个内部节点归纳:三元组相同当且仅当点权、左结构和右结构都相同,所以规范ID相等当且仅当有序带权树完全相同。镜像ID交换左右子树的镜像ID计算,因而普通ID等于镜像ID恰是对称;取这种节点的最大子树大小即答案。

    复杂度

    期望O(n)时间,极端哈希探测最坏O(n²);O(n)空间,含容量不小于4n的表清零和全部迭代数组;不用递归避免百万深链栈溢出。

    易错点

    哈希只决定存放槽,实际比较完整64位编码键,冲突线性探测处理,不以哈希值相等判结构相等。每个子ID最多2n,21位足够;点权<=1000。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        int n;
        cin >> n;
        vector<int> w(n + 1), l(n + 1), r(n + 1), sz(n + 1), a(n + 1), b(n + 1), order(1, 1);
        for (int i = 1; i <= n; i++)
            cin >> w[i];
        for (int i = 1; i <= n; i++) {
            cin >> l[i] >> r[i];
            l[i] = max(0, l[i]);
            r[i] = max(0, r[i]);
        }
        for (int i = 0; i < (int)order.size(); i++) {
            int u = order[i];
            if (l[u])
                order.push_back(l[u]);
            if (r[u])
                order.push_back(r[u]);
        }
        int cap = 1;
        while (cap < 4 * n)
            cap <<= 1;
        vector<unsigned long long> keys(cap);
        vector<int> ids(cap);
        int id = 0;
        auto intern = [&](int w, int a, int b) {
            unsigned long long key = ((unsigned long long)w << 42) | ((unsigned long long)a << 21) | b;
            unsigned long long h = key;
            h ^= h >> 30;
            h *= 0xbf58476d1ce4e5b9ULL;
            h ^= h >> 27;
            h *= 0x94d049bb133111ebULL;
            h ^= h >> 31;
            int s = h & (cap - 1);
            while (keys[s] && keys[s] != key)
                s = (s + 1) & (cap - 1);
            if (!keys[s]) {
                keys[s] = key;
                ids[s] = ++id;
            }
            return ids[s];
        };
        int ans = 1;
        for (int i = n - 1; i >= 0; i--) {
            int u = order[i];
            sz[u] = sz[l[u]] + sz[r[u]] + 1;
            a[u] = intern(w[u], a[l[u]], a[r[u]]);
            b[u] = intern(w[u], b[r[u]], b[l[u]]);
            if (a[u] == b[u])
                ans = max(ans, sz[u]);
        }
        cout << ans << "\n";
    }
    
    • 1

    信息

    ID
    1902
    时间
    1000ms
    内存
    256MiB
    难度
    普及
    标签
    递交数
    0
    已通过
    0
    上传者