2049: [Sdoi2008]Cave 洞穴勘测

来源:互联网 发布:购买域名后 备案 编辑:程序博客网 时间:2024/05/16 17:27

题目链接

题目大意:动态树,要求link,cut,查询两点连通性

题解:LCT,对于query操作,查询x在原树的根就好了。并查集乱搞能过……

我的收获:LCTget

#include <iostream>#include <cstdio>#define M 100005using namespace std;int n,m,y;int fa[M],c[M][2],st[M];bool rev[M];inline bool f(int x){return c[fa[x]][1]==x;}inline bool isr(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}void pushdown(int x){    if(!rev[x]) return ;    int &l=c[x][0],&r=c[x][1];    rev[l]^=1;rev[r]^=1;swap(l,r);    rev[x]=0;}void rotate(int x){    int p=fa[x],g=fa[p],r;    bool k=f(x),m=f(p);r=c[x][k^1];    if(!isr(p)) c[g][m]=x;    fa[x]=g,c[x][k^1]=p;    fa[p]=x,c[p][k]=r;    if(r) fa[r]=p;}void maintain(int x){    int top=0;st[++top]=x;    for(int i=x;!isr(i);i=fa[i]) st[++top]=fa[i];    for(int i=top;i;i--) pushdown(st[i]);}void splay(int x){    maintain(x);    for(;!isr(x);rotate(x))        if(!isr(fa[x])) rotate(f(x)==f(fa[x])?fa[x]:x);}void access(int x){for(y=0;x;c[x][1]=y,y=x,x=fa[x]) splay(x);}//取出当前点到当前根的这一段路径,将它们放到一个Splay中。void rever(int x){access(x);splay(x);rev[x]^=1;}//将x旋转到其所在树的树根 void link(int x,int y){rever(y);fa[y]=x;}//将y连到x的下面 void cut(int x,int y){rever(x);access(y);splay(y);fa[x]=c[y][0]=0;}//断开x和y之间的边 int fdrt(int x)//找x在原树中的根结点 {    access(x);splay(x);    for(y=x;c[y][0];y=c[y][0]);    return y;}void work(){    int x,y;    char opt[10];    while(m--)    {        scanf("%s",opt);        scanf("%d%d",&x,&y);        if(opt[0]=='C')link(x,y);        else if(opt[0]=='D')cut(x,y);        else puts(fdrt(x)==fdrt(y)?"Yes":"No");    }}void init(){    cin>>n>>m;}int main(){    init();    work();    return 0;}HOME Back