P1613 跑路

Miku

如果我们知道哪两个点可以用跑路机1s到达就好办了

怎么知道呢?如果两个点的距离可以为\(2^k\),那么一定有一个中转接点,到两个点的距离都是\(2^{k-1}\),也就是如此了。

这样显然可以用\(floyd\)预处理出来距离

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;
template<class T>inline void read(T &x)
{
    x=0;register char c=getchar();register bool f=0;
    while(!isdigit(c))f^=c=='-',c=getchar();
    while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
    if(f)x=-x;
}
template<class T>inline void print(T x)
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)print(x/10);
    putchar('0'+x%10);
}
unsigned long long prime[4];
int n;
int x,y;
int ans;
int sum[10000006];
int ls[1000006],rs[1000006];
unsigned long long has[1000006],val[10000006],Has[1000006],ha[10000006],Ha[10000006];
unsigned long long  mod=89999794200117649;
unsigned long long  modd=999999786000011449;
void dfs(int no){
	if(ls[no]!=-1) dfs(ls[no]);
	if(rs[no]!=-1) dfs(rs[no]);
	sum[no]=sum[ls[no]]+sum[rs[no]]+1;
	if(sum[ls[no]]==sum[rs[no]]&&has[ls[no]]==Has[rs[no]]&&ha[ls[no]]==Ha[rs[no]]){
		ans=max(ans,sum[no]);
	}
	has[no]=has[ls[no]]*prime[0]+val[no]*prime[1]+has[rs[no]]*prime[2];
	has[no]%=mod;
	Has[no]=Has[rs[no]]*prime[0]+val[no]*prime[1]+Has[ls[no]]*prime[2];
	Has[no]%=mod;
	ha[no]=ha[ls[no]]*prime[2]+val[no]*prime[1]+ha[rs[no]]*prime[0];
	ha[no]%=modd;
	Ha[no]=Ha[rs[no]]*prime[2]+val[no]*prime[1]+Ha[ls[no]]*prime[0];
	Ha[no]%=modd;
}
int main(){
	prime[0]=20041204;
	prime[1]=299999827;
	prime[2]=999999751;
	read(n);
	for(int i=1;i<=n;++i){
		read(val[i]);
	}
	for(int i=1;i<=n;++i){
		read(x);read(y);
		ls[i]=x;rs[i]=y;
	}
	dfs(1);
	cout<<ans;
	return 0;
}
posted @ 2021-10-31 12:13  Simex  阅读(16)  评论(0编辑  收藏  举报