[bzoj2049][Sdoi2008]Cave 洞穴勘測_LCT
阿新 • • 發佈:2018-07-08
com ces define true make .html bsp turn splay
Cave 洞穴勘測 bzoj-2049 Sdoi-2008
題目大意:維護一個數據結構,支持森林中加邊,刪邊,求兩點連通性。n個點,m個操作。
註釋:$1\le n\le 10^4$,$1\le m\le 2\cdot 10^5$。
想法:剛學了一發LCT,寫一道照學長抄一道板子題。話說什麽是LCT?
就是一個賊nb的數據結構,支持加邊刪邊後的什麽路徑和子樹信息啥的,這就是LCT。
艾歐欸軟可以的blog
這道題,我們只需要其中的link,cut和find即可。
最後,附上代碼.. ...
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define N 10050 #define ls ch[p][0] #define rs ch[p][1] #define get(x) (ch[f[x]][1]==x) using namespace std; int root[N],ch[N][2],n,m,rev[N],f[N]; char opt[10]; inline bool isroot(int p) { return ch[f[p]][0]!=p&&ch[f[p]][1]!=p; } inline void pushdown(int p) { if(!rev[p]) swap(ch[ls][0],ch[ls][1]); swap(ch[rs][0],ch[rs][1]); rev[ls]^=1; rev[rs]^=1; rev[p]=0; } void update(int p) { if(!isroot(p)) update(f[p]); pushdown(p); } void rotate(int x) { int y=f[x],z=f[y],k=get(x); if(!isroot(y)) ch[z][ch[z][1]==y]=x; ch[y][k]=ch[x][!k]; f[ch[y][k]]=y; ch[x][!k]=y; f[y]=x; f[x]=z; } void splay(int x) { update(x); for(int fa;fa=f[x],!isroot(x);rotate(x)) { if(!isroot(fa)) { rotate(get(fa)==get(x)?fa:x); } } } void access(int p) { int t=0; while(p) splay(p),rs=t,t=p,p=f[p]; } void makeroot(int p) { access(p); splay(p); swap(ls,rs); rev[p]^=1; } void link(int x,int p) { makeroot(x); f[x]=p; } void cut(int x,int p) { makeroot(x); access(p); splay(p); ls=f[x]=0; } int find(int p) { access(p); splay(p); while(ls) pushdown(p),p=ls; return p; } int main() { scanf("%d%d",&n,&m); int x,y; for(int i=1;i<=m;i++) { scanf("%s%d%d",opt,&x,&y); if(opt[0]==‘C‘) link(x,y); else if(opt[0]==‘D‘) cut(x,y); else { int t=find(x),b=find(y); puts(t==b?"Yes":"No"); } } }
小結:都說LCT出來就是板子題,但是得會敲才行啊???!!
[bzoj2049][Sdoi2008]Cave 洞穴勘測_LCT