洛谷 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

posted @ 2021-10-31 10:50  尹昱钦  阅读(220)  评论(0编辑  收藏  举报