1. 程式人生 > >2018.10.07【SDOI2008】【BZOJ2049】【洛谷P2147】Cave洞穴勘測(LCT)

2018.10.07【SDOI2008】【BZOJ2049】【洛谷P2147】Cave洞穴勘測(LCT)

洛谷傳送門

解析:

這是一道LCTLCT的裸題,卻不夠板。

思路:

這是LCTLCT的一個經典應用,維護動態樹上節點的聯通性。 對於基本操作我不再贅述,詳見我的LCTLCT模板(暫未更新)。

這道題就講一講怎麼維護聯通性。

由於同一聯通塊中的節點是由幾條被SplaySplay維護的重鏈所覆蓋的,我們判斷連通性的時候只需要將一個節點變為該聯通子樹的根,然後判斷另一個節點的SplaySplay根是否是它就行了。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register #define gc getchar #define pc putchar #define cs const inline int getint(){ re int num; re char c; while(!isdigit(c=gc()));num=c^48; while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48); return num; } inline char getalpha(){ re char c; while(!isalpha(c=gc()));
return c; } typedef struct splay_node *point; struct splay_node{ point son[2],fa; bool tag; void init(){son[0]=son[1]=fa=NULL,tag=0;} void pushdown(){ if(tag){ if(son[0])son[0]->tag^=1; if(son[1])son[1]->tag^=1; swap(son[0],son[1]); tag=0; } } point &lc(){return son[0];} point &
rc(){return son[1];} bool isroot(){return !fa||(fa->lc()!=this&&fa->rc()!=this);} bool which(){return this==fa->son[1];} }; cs int N=10004; struct Link_Cut_Tree{ point tr[N]; void init(int n){ for(int re i=0;i<=n;++i) tr[i]=(point)malloc(sizeof(splay_node)), tr[i]->init(); } void Rotate(point now){ point Fa=now->fa,FA=Fa->fa; if(FA&&!Fa->isroot())FA->son[Fa->which()]=now; Fa->fa=now; now->fa=FA; bool pos=now==Fa->lc(); point tmp=now->son[pos]; if(tmp)tmp->fa=Fa; Fa->son[!pos]=tmp; now->son[pos]=Fa; } void Splay(point now){ static point q[N]; static int qn; q[qn=1]=now; for(point Fa=now;!Fa->isroot();Fa=Fa->fa)q[++qn]=Fa->fa; for(int re i=qn;i;--i)q[i]->pushdown(); for(point Fa=now->fa;!now->isroot();Rotate(now),Fa=now->fa) if(!Fa->isroot())Rotate(now->which()==Fa->which()?Fa:now); } void access(point now){ for(point son=NULL;now;son=now,now=now->fa){ Splay(now);now->rc()=son; if(son)son->fa=now; } } void makeroot(point now){ access(now); Splay(now); now->tag^=1; } point findroot(point now){ access(now); Splay(now); while(now->lc())now=now->lc(); return now; } void link(point u,point v){makeroot(u);u->fa=v;} void Link(int u,int v){link(tr[u],tr[v]);} void cut(point u,point v){ makeroot(u),access(v); Splay(v); u->fa=NULL; v->lc()=NULL; } void Cut(int u,int v){cut(tr[u],tr[v]);} bool connect(point u,point v){ makeroot(u); point tmp=findroot(v); return tmp==u; } bool Connect(int u,int v){return connect(tr[u],tr[v]);} }LCT; int n,m; signed main(){ n=getint(),m=getint(); LCT.init(n); while(m--){ char op=getalpha(); int u=getint(),v=getint(); switch(op){ case 'C':{ LCT.Link(u,v); break; } case 'D':{ LCT.Cut(u,v); break; } case 'Q':{ puts(LCT.Connect(u,v)?"Yes":"No"); break; } } } return 0; }