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出来就是板子题,但是得会敲才行啊???!!
原文地址:https://www.cnblogs.com/ShuraK/p/9278737.html
时间: 2024-10-13 00:15:06