2018.12.12【BZOJ5192】【洛谷P4271】New Barns(LCT维护直径)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/84976437

BZOJ传送门

洛谷传送门


解析:

许久没有写LCT,手都有点生了。

思路:

这道题是显然的需要维护直径的,因为有结论,树上距离一个点的最远点一定是某个直径的端点。证明很显然,就不证了。

那么怎么维护动态的直径呢?

我们可以用LCT维护一个森林,对于每棵树记录直径的两个端点,加入一个新点的时候更新,我们有如下结论:新的直径与原来直径至少有一个端点重合。

那么LCT乱搞一波就做完了。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

namespace IO{
	inline int getint(){
		re int num;
		re char c;
		re bool f=0;
		while(!isdigit(c=gc()))if(c=='-')f=1;num=c^48;
		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
		return f?-num:num;
	}
	
	inline void outint(int a){
		static char ch[23];
		if(a==0)pc('0');
		while(a)ch[++ch[0]]=a-a/10*10,a/=10;
		while(ch[0])pc(ch[ch[0]--]^48);
	}
	
	inline char getalpha(){
		re char c;
		while(!isalpha(c=gc()));
		return c;
	}
}
using namespace IO;

typedef struct splay_node *point;
struct splay_node{
	point fa,son[2];
	int siz;
	bool tag;
	splay_node(){fa=son[0]=son[1]=NULL;siz=1;tag=0;}
	#define lc son[0]
	#define rc son[1]
	inline bool isroot(){return !fa||(fa->lc!=this&&fa->rc!=this);}
	inline bool which(){return fa->rc==this;}
	inline void pushdown(){
		if(tag){
			if(lc)lc->tag^=1;
			if(rc)rc->tag^=1;
			swap(lc,rc);
			tag=false;
		}
	}
	inline void pushup(){
		siz=(lc?lc->siz:0)+(rc?rc->siz:0)+1;
	}
};

point newnode(){
	point p=(point)malloc(sizeof(splay_node));
	*p=splay_node();
	return p;
}

cs int N=100005;
int bcnt,tot;
int block[N];
point l[N],r[N];
point tr[N];

inline void Rotate(point now){
	point Fa=now->fa,FA=Fa->fa;
	bool pos=now->which();
	if(FA&&!Fa->isroot())FA->son[Fa->which()]=now;
	Fa->son[pos]=now->son[!pos];
	if(Fa->son[pos])Fa->son[pos]->fa=Fa;
	now->son[!pos]=Fa;
	Fa->fa=now;
	now->fa=FA;
	Fa->pushup();
	now->pushup();
}

inline void Splay(point now){
	static point q[N];static int qn=0;
	q[qn=1]=now;
	for(re point Fa=now;!Fa->isroot();Fa=Fa->fa)q[++qn]=Fa->fa;
	for(int re i=qn;i;--i)q[i]->pushdown();
	for(re point Fa=now->fa;!now->isroot();Rotate(now),Fa=now->fa)
	if(!Fa->isroot())Rotate(now->which()==Fa->which()?Fa:now);
}

inline void access(point now){
	for(re point son=NULL;now;son=now,now=now->fa)
	Splay(now),now->rc=son,now->pushup();
}

inline void makeroot(point now){
	access(now);
	Splay(now);
	now->tag^=1;
}

inline void link(point u,point v){
	makeroot(u);
	u->fa=v;
}

inline int query(point u,point v){
	makeroot(u);
	access(v);
	Splay(v);
	return v->siz-1;
}

int Q;
signed main(){
	Q=getint();
	while(Q--){
		re char op=getalpha();
		re int u=getint();
		switch(op){
			case 'B':{
				tr[++tot]=newnode();
				if(~u){
					re int b=block[tot]=block[u];
					link(tr[tot],tr[u]);
					re int d1=query(tr[tot],l[b]),d2=query(l[b],r[b]);
					if(d1>d2)r[b]=tr[tot];
					d1=query(tr[tot],r[b]);
					if(d1>d2)l[b]=tr[tot];
				}
				else{
					block[tot]=++bcnt;
					l[bcnt]=tr[tot];
					r[bcnt]=tr[tot];
				}
				break;
			}
			case 'Q':{
				re int b=block[u];
				outint(max(query(tr[u],l[b]),query(tr[u],r[b])));pc('\n');
				break;
			}
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/84976437