zoukankan      html  css  js  c++  java
  • Query on a tree again! SPOJ

    https://vjudge.net/problem/SPOJ-QTREE3

    https://www.luogu.org/problemnew/show/P4116

    一个log(LCT)比两个log(树剖)慢到不知道哪里去系列。。。

      1 #pragma GCC optimize("Ofast")
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<vector>
      6 using namespace std;
      7 #define fi first
      8 #define se second
      9 #define mp make_pair
     10 #define pb push_back
     11 typedef long long ll;
     12 typedef unsigned long long ull;
     13 typedef pair<int,int> pi;
     14 
     15 namespace LCT
     16 {
     17 struct Node
     18 {
     19     Node *ch[2],*fa;
     20     bool rev;
     21     bool d;Node *dd;
     22     int id;
     23     void upd()
     24     {
     25         if(ch[0]&&ch[0]->dd)    dd=ch[0]->dd;
     26         else if(d)    dd=this;
     27         else dd=ch[1]?ch[1]->dd:0;
     28     }
     29     void pd()
     30     {
     31         if(rev)
     32         {
     33             swap(ch[0],ch[1]);
     34             if(ch[0])    ch[0]->rev^=1;
     35             if(ch[1])    ch[1]->rev^=1;
     36             rev=0;
     37         }
     38     }
     39 }nodes[300100];
     40 int mem;
     41 Node *getnode()
     42 {
     43     return nodes+(mem++);
     44 }
     45 bool isroot(Node *x)
     46 {
     47     return (!x->fa)||((x->fa->ch[0]!=x)&&(x->fa->ch[1]!=x));
     48 }
     49 bool gson(Node *o)    {return o==o->fa->ch[1];}
     50 void rotate(Node *o,bool d)
     51 {
     52     Node *k=o->ch[!d];if(!isroot(o))    o->fa->ch[gson(o)]=k;
     53     o->ch[!d]=k->ch[d];k->ch[d]=o;
     54     o->upd();k->upd();
     55     k->fa=o->fa;o->fa=k;if(o->ch[!d])    o->ch[!d]->fa=o;
     56 }
     57 Node *st[300100];int top;
     58 void solvetag(Node *o)
     59 {
     60     while(!isroot(o))    st[++top]=o,o=o->fa;
     61     st[++top]=o;
     62     while(top)    st[top--]->pd();
     63 }
     64 void splay(Node *o)
     65 {
     66     solvetag(o);
     67     Node *fa,*fafa;bool d1,d2;
     68     while(!isroot(o))
     69     {
     70         fa=o->fa;d1=(o==fa->ch[0]);
     71         if(isroot(fa))    rotate(fa,d1);
     72         else
     73         {
     74             fafa=o->fa->fa;d2=(fa==fafa->ch[0]);//要保证fa不是root之后才能获取这两个值,曾错过
     75             if(d1==d2)    rotate(fafa,d1),rotate(fa,d1);//zig-zig,两次相同方向的单旋,先把父亲转上去,再把自己转上去
     76             else    rotate(fa,d1),rotate(fafa,d2);//zig-zag,两次相反方向的单旋,连续两次把自己转上去
     77         }
     78     }
     79 }
     80 void access(Node *o)
     81 {
     82     for(Node *lst=NULL;o;lst=o,o=o->fa)
     83     {
     84         splay(o);//此处不pushdown是由于splay中保证进行过了
     85         o->ch[1]=lst;o->upd();//注意upd
     86     }
     87 }
     88 Node *gtop(Node *o)
     89 {
     90     access(o);splay(o);
     91     for(;o->ch[0];o=o->ch[0],o->pd());//此处不在开始前pushdown(o)是由于splay中保证进行过了
     92     splay(o);return o;//听说这里不splay一下也很难卡掉
     93 }
     94 void mtop(Node *o)    {access(o);splay(o);o->rev^=1;}
     95 void link(Node *x,Node *y)
     96 {
     97     if(gtop(x)==gtop(y))    return;
     98     mtop(y);y->fa=x;
     99 }
    100 void cut(Node *x,Node *y)
    101 {
    102     mtop(x);access(y);splay(y);
    103     if(y->ch[0]!=x||x->ch[1])    return;//如果x、y之间直接有边,那么上面一行的操作之后应当是x与y在单独一棵splay中,那么一定保证y左子节点是x且x没有右子节点
    104     x->fa=y->ch[0]=NULL;//注意,改的是x的父亲和y的子节点(虽然x的确是树的根,但是此时在splay上是y的子节点,不能搞混)
    105     y->upd();//注意
    106 }
    107 void change(Node *y)
    108 {
    109     access(y);splay(y);
    110     y->d^=1;y->upd();
    111 }
    112 int query(Node *x,Node *y)
    113 {
    114     mtop(x);access(y);splay(y);
    115     return y->dd?y->dd->id:-1;
    116 }
    117 }
    118 LCT::Node *nd[300100];
    119 int n,q;
    120 int main()
    121 {
    122     int i,idx,x,a,b;
    123     scanf("%d%d",&n,&q);
    124     for(i=1;i<=n;i++)    nd[i]=LCT::getnode(),nd[i]->id=i;
    125     for(i=1;i<n;i++)
    126     {
    127         scanf("%d%d",&a,&b);
    128         LCT::link(nd[a],nd[b]);
    129     }
    130     while(q--)
    131     {
    132         scanf("%d%d",&idx,&x);
    133         if(idx==0)    LCT::change(nd[x]);
    134         else    printf("%d
    ",LCT::query(nd[1],nd[x]));
    135     }
    136     return 0;
    137 }
  • 相关阅读:
    python类型转换
    手机抓包
    java容器collection的一些简单特点
    WIN7 如何将BAT文件附加到任务栏
    Android新权限机制 AppOps
    记录一写Android常用API
    关于java建立的的包import的问题
    Android组件安全
    查看字节码
    数据库分表之Mybatis+Mysql实践(含部分关键代码)
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9282810.html
Copyright © 2011-2022 走看看