和直径相关的性质:CF842E

https://codeforces.com/contest/842/problem/E

关键性质:多条直径点的交集必然非空且一定为连续一段

也就是说:必然可以划分成两个集合,使得两个集合各选一个点上的路径必然为一条直径

然后对于此题求端点,我们就可以维护两个集合,然后就行了

至于这题有什么启发,我现在还没想懂

#include
using namespace std;
//#define int long long
inline int read(){int x=0,f=1;char ch=getchar(); while(ch<'0'||
ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
//mt19937 rand(time(0));
//mt19937_64 rand(time(0));
//srand(time(0));
#define N 300010
//#define M
//#define mo
int n, m, i, j, k, T;
int u, d1, d2, mxd, dia; 
int dep[N], f[N][22]; 
vector<int>v1, v2; 

int lca(int u, int v) {
	if(u==v) return u; 
	if(dep[u]<dep[v]) swap(u, v); 
	for(int k=20; k>=0; --k) 
		if(dep[f[u][k]]>=dep[v]) u=f[u][k]; 
//	printf("%d %d %d\n", u, v, f[u][0]); 
	if(u==v) return u; 
	for(int k=20; k>=0; --k)
		if(f[u][k]!=f[v][k]) u=f[u][k], v=f[v][k]; 
	return f[u][0]; 
}

int dis(int x, int y) {
	int z=lca(x, y); 
//	printf("dis(%d %d)[%d]=%d\n", x, y, z, dep[x]+dep[y]-2*dep[z]); 
	return dep[x]+dep[y]-2*dep[z]; 
}

signed main()
{
//	freopen("in.txt", "r", stdin);
//	freopen("out.txt", "w", stdout);
//	T=read();
//	while(T--) {
//
//	}
	n=read(); dep[1]=1; 
	for(i=2; i<=n+1; ++i) {
		u=read(); f[i][0]=u; dep[i]=dep[u]+1;
//		printf("f[%lld][0]=%lld\n", i, f[i][0]) ; 
		for(k=1; k<=20; ++k) f[i][k]=f[f[i][k-1]][k-1]; 
		if(i==2) {
			v1.pb(1); v2.pb(2); dia=1; 
			printf("%lld\n", v1.size()+v2.size()); 
			continue; 
		}
		d1=dis(v1[0], i); d2=dis(v2[0], i); mxd=max(d1, d2); 
		if(mxd>dia) {
			if(d1>dia) {
				for(auto j : v2) if(dis(j, i)==mxd) v1.pb(j); 
				v2.clear(), v2.pb(i); 
			}
			else {
				for(auto j : v1) if(dis(j, i)==mxd) v2.pb(j); 

				v1.clear(), v1.pb(i); 
			}
			dia=mxd; 
		}
		else if(mxd==dia) {
			if(d1==dia) v2.pb(i); 
			else v1.pb(i); 
		}
		printf("%lld\n", v1.size()+v2.size()); 
//		printf("dia : %lld || ", dia); 
//		for(auto i : v1) printf("%lld ", i); printf(" | "); 
//		for(auto i : v2) printf("%lld ", i); printf("\n"); 
	}
	return 0;
}


你可能感兴趣的:(直径)