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