洛谷 P5018 [NOIP2018 普及组] 对称二叉树(树哈希)
传送门
传送门
判断节点u的子树是否是对称二叉树的方法:
判断hash1[l[u]]是否等于hash2[r[u]]。
其中hash1中存的是按照根左右的顺序的哈希值,hash2存的是按照根右左顺序的哈希值。
当两个hash值相等时,即为对称二叉树。
单哈希和双哈希貌似都不太稳定,而用自然溢出即可AC本题。
AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<vector>
using namespace std;
const int maxn=1e6+5;
const unsigned long long p1=1000000007;
const unsigned long long p2=9999994751;
const unsigned long long p3=5999995827;
const unsigned long long mod=899800117649;
int n,v[maxn],l[maxn],r[maxn],siz[maxn],ans;
unsigned long long dp1[maxn],dp2[maxn];
void dfs(int u){
siz[u]=1;
dp1[u]=dp2[u]=p1*v[u]%mod;
if(~l[u]) dfs(l[u]),siz[u]+=siz[l[u]],dp1[u]=(dp1[u]+p2*dp1[l[u]])%mod,dp2[u]=(dp2[u]+p3*dp2[l[u]])%mod;
if(~r[u]) dfs(r[u]),siz[u]+=siz[r[u]],dp1[u]=(dp1[u]+p3*dp1[r[u]])%mod,dp2[u]=(dp2[u]+p2*dp2[r[u]])%mod;
}
void dfs2(int u){
if(l[u]==-1&&r[u]==-1){
ans=max(ans,1);
return;
}
if(l[u]!=-1&&r[u]!=-1){
if(siz[l[u]]==siz[r[u]]&&dp1[l[u]]==dp2[r[u]]){
ans=max(ans,siz[u]);
return;
}
}
if(~l[u]) dfs2(l[u]);
if(~r[u]) dfs2(r[u]);
}
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++) cin>>v[i];
for(int i=1;i<=n;i++){
cin>>l[i]>>r[i];
}
dfs(1);
dfs2(1);
cout<<ans<<endl;
return 0;
}
//NOIP2018普及组 t4