• spoj DYNALCA


    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
    ",LCT::lca(nd[x],nd[y])->num);
    134             break;
    135         }
    136     }
    137     return 0;
    138 }
  • 相关阅读:
    mysql将一个表的数据 重复复制多份到表中
    PHP中将指定文本内容导入到word中
    系统安全-SElinux
    通过身份证号码提取年龄,性别
    MySQL-获取某天的数据
    mysql-介绍、MySQL部署、数据类型、存储引擎
    监控系统-ELK
    监控系统-Grafana
    监控系统-zabbix
    监控系统-openfalcon
  • 原文地址:https://www.cnblogs.com/hehe54321/p/8969671.html
Copyright © 2020-2023  润新知