• BZOJ2049 [SDOI2008]Cave 洞穴勘测


    Link-Cut Tree

    把每个重链看成是一个splay

    mroot:将x整到splay根上,将这个splay上下左右翻转

    这个根的左儿子是他上面的重链,右儿子是他下面的重链

    access:将根(最最上面)到x的边看成一条重链

    link:连接两点都到根上,再更新

    cut:切除两点关系,先将x转到根上,再把y到最最上面根的路变为重链,那么一定会经过x,然后将y旋到根上,删除关系即可。

    find:将他翻到根然后找这棵树中深度最小的。

    我一开始有两点疑惑1为什么mroot操作要左右翻转

    因为我们翻转之前他的深度是最大的,但我们翻转之后他虽然在splay中表现出来的依旧深度最大但我们需要让他变为深度最小的,所以比他大的要全去右边。

    第二个是我们为什么要让他变为深度最小的

    因为我们在cut和link操作中依照splay的性质将y转到根上然后让x做他的左儿子条件是x是深度最小的,

    而且link操作里你连边相当于把两棵树接在一起,如果这两个点中没有一个点是根节点的话那么这个点就会有两个父亲从而不满足树的形态。

    在find操作里我们只需要找比他小的所以没有必要加。或者你可以sb一样的加reverse然后splay到根再找根的右儿子的最左儿子。

    By:大奕哥

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=1e5+10;
     4 int n,m,fa[N],c[N][2],st[N];
     5 bool rev[N];char s[10];
     6 void pushdown(int x)
     7 {
     8     if(rev[x])
     9     {
    10         rev[c[x][0]]^=1;rev[c[x][1]]^=1;
    11         swap(c[x][0],c[x][1]);rev[x]=0;
    12     }
    13 }
    14 inline bool isroot(int x)
    15 {
    16     return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
    17 }
    18 void rotate(int x)
    19 {
    20     int y=fa[x],z=fa[y],l,r;
    21     l=c[y][1]==x;r=l^1;
    22     if(!isroot(y))c[z][c[z][1]==y]=x;
    23     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
    24     c[y][l]=c[x][r];c[x][r]=y;
    25 }
    26 void splay(int x)
    27 {
    28     int top=0;int i;
    29     for(i=x;!isroot(i);i=fa[i])st[++top]=i;
    30     st[++top]=i;
    31     for(i=top;i;--i)pushdown(st[i]);
    32     while(!isroot(x))
    33     {
    34         int y=fa[x],z=fa[y];
    35         if(!isroot(y))
    36         {
    37             if(c[y][0]==x^c[z][0]==y)rotate(x);
    38             else rotate(y);
    39         }
    40         rotate(x);
    41     }
    42 }
    43 void access(int x)
    44 {
    45     int y=0;
    46     while(x)
    47     {
    48         splay(x);
    49         c[x][1]=y;
    50         y=x;x=fa[x];
    51     }
    52 }
    53 void mroot(int x)
    54 {
    55     access(x);splay(x);rev[x]^=1;
    56 }
    57 void link(int x,int y)
    58 {
    59     mroot(x);fa[x]=y;splay(x);
    60 }
    61 void cut(int x,int y)
    62 {
    63     mroot(x);access(y);splay(y);c[y][0]=fa[x]=0;
    64 }
    65 int find(int x)
    66 {
    67     access(x);splay(x);
    68     int y=x;
    69     while(c[y][0])y=c[y][0];
    70     return y;
    71 }
    72 int main()
    73 {
    74     scanf("%d%d",&n,&m);int x,y;
    75     for(int i=1;i<=m;++i)
    76     {
    77         scanf("%s%d%d",s,&x,&y);
    78         if(s[0]=='C')link(x,y);
    79         else if(s[0]=='D')cut(x,y);
    80         else{
    81             if(find(x)==find(y))puts("Yes");
    82             else puts("No");
    83         }
    84     }
    85     return 0;
    86 }
  • 相关阅读:
    asp读书笔记(二)内置对象
    网上收集的关于iframe的自适应高度代码js的
    第一遇到地震,虽然小点
    给网友写的控制页面元素高度的代码(js)
    给用户控件添加可枚举的属性
    标记(Tagging)能给网站带来的7大益处
    代码最重要的读者不再是编译器、解释器或者电脑,而是人!
    亚洲超大数据库会议(XLDB Asia 2012)
    每年15万美元!这是开发人员解决构造问题的总成本!
    华章IT图书书讯(2012年第7期)
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8334354.html
Copyright © 2020-2023  润新知