4.17 Torneo electoral provincial Multiplicador de fusión heurística LCT

avatar
avatar

Es fácil escribir la violencia de nQ. Dado que los datos son el tiempo esperado, los dfs directos pueden ejecutarse rápidamente y pueden obtener 70 puntos.

Por supuesto, la violencia puede optimizarse aún más mediante el uso de root dp y luego la violencia puede optimizarse a n ^ 2.

const int MAXN=300010;
int n,Q,T,len,maxx;
int lin[MAXN],d[MAXN],ver[MAXN<<1],nex[MAXN<<1];
inline void add(int x,int y)
{
	ver[++len]=y;
	nex[len]=lin[x];
	lin[x]=len;
}
inline void dfs(int x,int y)
{
	d[x]=d[y]+1;
	maxx=max(maxx,d[x]-1);
	go(x)if(tn!=y)dfs(tn,x);
}
int main()
{
	freopen("hike.in","r",stdin);
	freopen("hike.out","w",stdout);
	get(T);get(n);get(Q);
	rep(1,Q,i)
	{
		int op,x,y;
		get(op);get(x)^(T*maxx);
		if(op==1)get(y)^(T*maxx),add(x,y),add(y,x);
		else maxx=0,dfs(x,0),put(maxx);
	}
	return 0;
}

Considera sin conexión. Se puede encontrar que la violencia todavía es necesaria cada vez.

Piense más sobre la naturaleza especial del punto más alejado del árbol.

No es difícil pensar que el diámetro del árbol se puede encontrar en que el punto más alejado de un punto debe ser uno de los extremos rectos.

Esto no es difícil de probar. Discuta si el camino cruza el diámetro o no.

De hecho, necesitamos mantener los extremos rectos hacia abajo de un árbol Unicom.

Puedes construir el árbol sin conexión.

Entonces es relativamente sencillo fusionar los puntos más alejados de los dos conjuntos, lo que puede demostrar que los extremos del nuevo diámetro están entre estos cuatro puntos.

En cuanto a la prueba, la discusión es similar a la anterior.

De esta manera, podemos usar la matriz multiplicada del árbol original para encontrar la distancia entre dos puntos.

Considerar la posibilidad de encontrar la distancia entre dos puntos en línea es difícil de encontrar. Considere la fusión heurística y luego reprocese violentamente la matriz multiplicadora.

De esta manera, cada punto se reconstruye a lo sumo veces, y cada actualización de la matriz multiplicadora es nlog ^ 2 + Qlogn, aunque se puede pasar.

Pero considere mejores prácticas.

La conectividad del árbol de mantenimiento es fácil de pensar en LCT.

Al conectar los bordes, simplemente mantenga el punto final del diámetro del bloque conectado. La distancia entre los dos puntos también es fácil de encontrar.

Un conjunto como root y otro de acceso y finalmente verifican el tamaño de la pantalla.

Complejidad nlogn + Qlogn.

const int MAXN=300010;
int n,Q,T,maxx,top;
int f[MAXN],L[MAXN],s[MAXN],R[MAXN],re[MAXN],fa[MAXN],c[MAXN][2],sz[MAXN];//sz[x]表示x所在splay中的节点个数.
inline int getfather(int x){return x==fa[x]?x:fa[x]=getfather(fa[x]);}
inline int pd(int x){return c[f[x]][1]==x||c[f[x]][0]==x;}
inline void rev(int x)
{
	if(!x)return;
	swap(c[x][0],c[x][1]);
	re[x]^=1;
}
inline void pushup(int x)
{
	sz[x]=sz[c[x][0]]+sz[c[x][1]]+1;
}
inline void pushdown(int x){if(re[x])rev(c[x][0]),rev(c[x][1]),re[x]=0;}
inline void rotate(int x)
{
	int old=f[x],oldf=f[old],k=c[old][1]==x;
	c[old][k]=c[x][k^1];c[x][k^1]=old;
	if(pd(old))c[oldf][c[oldf][1]==old]=x;
	if(c[old][k])f[c[old][k]]=old;
	f[old]=x;f[x]=oldf;pushup(old);
}
inline void splay(int x)
{
	int y=x;top=0;
	s[++top]=y;
	while(pd(y))s[++top]=y=f[y];
	while(top)pushdown(s[top--]);
	while(pd(x))
	{
		int old=f[f[x]];
		if(pd(f[x]))rotate(((c[f[x]][0]==x)^(c[old][0]==f[x]))?x:f[x]);
		rotate(x);
	}
	pushup(x);return;
}
inline void access(int x)
{
	for(int y=0;x;x=f[y=x])
	{
		splay(x);
		c[x][1]=y;
		pushup(x);
	}
}
inline void make_root(int x)
{
	access(x);splay(x);
	rev(x);
}
inline int dis(int x,int y)
{
	make_root(x);
	access(y);
	splay(y);
	return sz[y];
}
inline void merge(int x,int y)
{
	int xx=getfather(x);
	int yy=getfather(y);
	int s1,s2,s3,s4;
	s1=L[xx],s2=L[yy];
	s3=R[xx],s4=R[yy];
	int l=0,r=0,w=0;
	int ww=dis(s1,s2);
	if(ww>w)w=ww,l=s1,r=s2;
	ww=dis(s1,s3);
	if(ww>w)w=ww,l=s1,r=s3;
	ww=dis(s1,s4);
	if(ww>w)w=ww,l=s1,r=s4;
	ww=dis(s2,s3);
	if(ww>w)w=ww,l=s2,r=s3;
	ww=dis(s2,s4);
	if(ww>w)w=ww,l=s2,r=s4;
	ww=dis(s3,s4);
	if(ww>w)w=ww,l=s3,r=s4;
	fa[xx]=yy;L[yy]=l;R[yy]=r;
}
inline void LINK(int x,int y)
{
	make_root(x);f[x]=y;
	merge(x,y);
}
int main()
{
	freopen("1.in","r",stdin);
	get(T);get(n);get(Q);
	rep(1,n,i)sz[i]=1,L[i]=R[i]=i,fa[i]=i;
	rep(1,Q,i)
	{
		int op,x,y;
		get(op);get(x)^(T*maxx);
		if(op==1)get(y)^(T*maxx),LINK(x,y);
		else 
		{
			int xx=getfather(x);
			maxx=max(dis(x,L[xx]),dis(x,R[xx]))-1;
			put(maxx);
		}
	}
	return 0;
}

Supongo que te gusta

Origin www.cnblogs.com/chdy/p/12721878.html
Recomendado
Clasificación