1 条题解
-
0
思路与算法
迭代后序计算普通结构和镜像结构的规范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