4.17 Provincial Election Tournament LCT Heuristic Merge Multiplier

avatar
avatar

It is easy to write out the violence of nQ. Since the data is the expected time, the direct dfs can run quickly and can get 70 points.

Of course, the violence can be further optimized by using root dp and then the violence can be optimized to 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;
}

Consider offline. It can be found that violence is still needed every time.

Think further about the special nature of the furthest point on the tree.

It is not difficult to think that the diameter of the tree can be found that the farthest point of a point must be one of the straight ends.

This is not difficult to prove. Discuss whether the path crosses the diameter or not.

In fact, we need to maintain the straight down ends of a Unicom tree.

You can build the tree offline.

Then it is relatively simple to merge the furthest points of the two sets, which can prove that the ends of the new diameter are among these four points.

As for the proof, the discussion is similar to the above.

In this way, we can use the multiplied array of the original tree to find the distance between two points.

Consider finding the distance between two points online is difficult to find. Consider heuristic merge and then violently reprocess the multiplier array.

In this way, each point is reconstructed logn times at most, and each update of the multiplier array is nlog ^ 2 + Qlogn, although it can be passed.

But consider better practices.

The connectivity of the maintenance tree is easy to think of LCT.

When connecting the edges, just maintain the diameter endpoint of the connected block. The distance between the two points is also easy to find.

One set as root and one access and finally check the splay size.

Complexity 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;
}

Guess you like

Origin www.cnblogs.com/chdy/p/12721878.html