1. 程式人生 > >2018.12.12【BZOJ5192】【洛谷P4271】New Barns(LCT維護直徑)

2018.12.12【BZOJ5192】【洛谷P4271】New Barns(LCT維護直徑)

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