spoj DYNALCA - Dynamic LCA

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spoj DYNALCA - Dynamic LCA相关的知识,希望对你有一定的参考价值。

http://www.spoj.com/problems/DYNALCA/

此题link、cut要求不能换根,当然也保证link时其中一个点必定已经是根。

方法:

void link(Node *x,Node *y)
{
    access(x);splay(x);
    x->fa=y;
}
void cut(Node *x)
{
    access(x);splay(x);
    x->ch[0]->fa=NULL;x->ch[0]=NULL;
}

曾经的错误思路:

void cut(Node *x)
{
    access(x->fa);x->fa=NULL;
}

因为此时x->fa不一定是splay维护的序列上x的前一个元素(只是splay上x的父亲罢了,在实际序列中它们的关系可以任意)

求lca?x,y的lca就是先access(x)后,在access(y)的过程中,“最后一次虚边变成实边的位置”。实际也就是access(y)的过程中最后一次的lst

  1 #include<cstdio>
  2 #include<algorithm>
  3 using namespace std;
  4 namespace LCT
  5 {
  6 struct Node
  7 {
  8     Node *ch[2],*fa;
  9     bool rev;
 10     int num;
 11     void upd()    {}
 12     void pd()
 13     {
 14         if(rev)
 15         {
 16             swap(ch[0],ch[1]);
 17             if(ch[0])    ch[0]->rev^=1;
 18             if(ch[1])    ch[1]->rev^=1;
 19             rev=0;
 20         }
 21     }
 22 }nodes[100100];
 23 int mem;
 24 Node *getnode()
 25 {
 26     return nodes+(mem++);
 27 }
 28 bool isroot(Node *x)
 29 {
 30     return (!x->fa)||((x->fa->ch[0]!=x)&&(x->fa->ch[1]!=x));
 31 }
 32 bool gson(Node *o)    {return o==o->fa->ch[1];}
 33 void rotate(Node *o,bool d)
 34 {
 35     Node *k=o->ch[!d];if(!isroot(o))    o->fa->ch[gson(o)]=k;
 36     o->ch[!d]=k->ch[d];k->ch[d]=o;
 37     o->upd();k->upd();
 38     k->fa=o->fa;o->fa=k;if(o->ch[!d])    o->ch[!d]->fa=o;
 39 }
 40 Node *st[300100];int top;
 41 void solvetag(Node *o)
 42 {
 43     while(!isroot(o))    st[++top]=o,o=o->fa;
 44     st[++top]=o;
 45     while(top)    st[top--]->pd();
 46 }
 47 void splay(Node *o)
 48 {
 49     solvetag(o);
 50     Node *fa,*fafa;bool d1,d2;
 51     while(!isroot(o))
 52     {
 53         fa=o->fa;d1=(o==fa->ch[0]);
 54         if(isroot(fa))    rotate(fa,d1);
 55         else
 56         {
 57             fafa=o->fa->fa;d2=(fa==fafa->ch[0]);
 58             if(d1==d2)    rotate(fafa,d1),rotate(fa,d1);
 59             else    rotate(fa,d1),rotate(fafa,d2);
 60         }
 61     }
 62 }
 63 void access(Node *o)
 64 {
 65     for(Node *lst=NULL;o;lst=o,o=o->fa)
 66     {
 67         splay(o);
 68         o->ch[1]=lst;o->upd();
 69     }
 70 }
 71 Node *gtop(Node *o)
 72 {
 73     access(o);splay(o);
 74     for(;o->ch[0];o=o->ch[0],o->pd());
 75     splay(o);return o;
 76 }
 77 void mtop(Node *o)    {access(o);splay(o);o->rev^=1;}
 78 void link(Node *x,Node *y)
 79 {
 80     access(x);splay(x);
 81     x->fa=y;
 82 }
 83 //void splay(Node *o,Node *rt)
 84 //{
 85 //    if(isroot(rt))    splay(o);
 86 //    bool d=gson(rt);Node *t=rt->fa;
 87 //    t->ch[d]=NULL;rt->fa=NULL;
 88 //    splay(o);
 89 //    t->ch[d]=o;o->fa=t;
 90 //}
 91 void cut(Node *x)
 92 {
 93     access(x);splay(x);
 94     x->ch[0]->fa=NULL;x->ch[0]=NULL;
 95 }
 96 Node *lca(Node *x,Node *y)
 97 {
 98     access(x);Node *lst=NULL;
 99     for(;y;lst=y,y=y->fa)
100     {
101         splay(y);
102         y->ch[1]=lst;y->upd();
103     }
104     return lst;
105 }
106 }
107 LCT::Node *nd[300100];
108 int n,q;char tmp[20];
109 int main()
110 {
111     int i,x,y;
112     scanf("%d%d",&n,&q);
113     for(i=1;i<=n;i++)
114     {
115         nd[i]=LCT::getnode();
116         nd[i]->num=i;
117     }
118     while(q--)
119     {
120         scanf("%s",tmp);
121         switch(tmp[1])
122         {
123         case i:
124             scanf("%d%d",&x,&y);
125             LCT::link(nd[x],nd[y]);
126             break;
127         case u:
128             scanf("%d",&x);
129             LCT::cut(nd[x]);
130             break;
131         case c:
132             scanf("%d%d",&x,&y);
133             printf("%d\n",LCT::lca(nd[x],nd[y])->num);
134             break;
135         }
136     }
137     return 0;
138 }

以上是关于spoj DYNALCA - Dynamic LCA的主要内容,如果未能解决你的问题,请参考以下文章

题解Luogu SP8791 DYNALCA - Dynamic LCA

Spoj-COINS-记忆化dp

SPOJ GSS系列(数据结构维护技巧入门)

CIT 593 Dynamic Memory

为啥我的 SPOJ GCD2 代码在 SPOJ 上出错?

SPOJ 问题 - 这里出了啥问题?