zoukankan      html  css  js  c++  java
  • BZOJ 1036 动态树

    这是一个比较经典的动态树模型,对于理解动态树还是很管用的~

    动态树就是很多splay组成的,每颗splay维护的是一条树链,splay之间用fa[]相连,如fa[x]=y表示以x为根的splay树的父亲是y,但是y的两个儿子(son[y][0]和son[y][1])中没有一个是x

    相对的,splay之间的父子关系也是通过fa[]和son[][]来维护的,不同的是,如果fa[x]=y,则必有son[y][0]或者son[y][1]等于x,这个一定要想明白!

    对于无向图,就是先bfs建树,此时每一个点都是一颗splay,因为对于任意fa[x]=y,son[y][0]和son[y][1]一定不是x

    isroot(x):判断x是否为其所在splay树的根(依据上述关系)

    splay(x):将x旋转为其所在的splay树的根

    access(x):将x到root(即原树的根,不同于x所在的splay树的根)的路径变成实边,注意理解函数中y的意义

    querysum(x,y)/querymax(x,y):求x到y的路径上的点权和/最大点权,实质就是求包含x和y的splay的lca

      先access(x),此时从x到root变成一条实边,即在同一颗splay树种(此时x向下的实边已经断开了,也就是说x是其所在splay树种深度最大的点了)

      再access(y),此时从y到root变成一条实边,返回值就是lca(画个图挺好理解的,这里一定要想明白!)

    其实动态树的精髓是link和cut,要加上旋转标记,就是将一颗splay树维护的链全部反向

    以上是我的理解,应该是对的。。。嘿嘿。

    代码觉得挺简单易懂的,可以看一下~

    View Code
      1 #include <iostream>
      2 #include <algorithm>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 
      7 #define N 500000
      8 #define INF 0x7f7f7f7f
      9 
     10 using namespace std;
     11 //http://www.cnblogs.com/proverbs/archive/2013/01/04/2845053.html
     12 int n,m,cnt;
     13 bool vis[N];
     14 int to[N],next[N],head[N],q[N];
     15 int fa[N],son[N][2],mx[N],val[N],sum[N];
     16 
     17 inline void pushup(int x)
     18 {
     19     if(!x) return;
     20     mx[x]=max(val[x],max(mx[son[x][0]],mx[son[x][1]]));
     21     sum[x]=sum[son[x][0]]+sum[son[x][1]]+val[x];
     22 }
     23 
     24 inline bool isroot(int x)
     25 {
     26     return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
     27 }
     28 
     29 inline void link(int x,int y,int c)
     30 {
     31     fa[x]=y; son[y][c]=x;
     32 }
     33  
     34 inline void rotate(int x,int c)
     35 {
     36     int y=fa[x];
     37     if(!isroot(y)) link(x,fa[y],son[fa[y]][1]==y);
     38     else fa[x]=fa[y];
     39     link(son[x][!c],y,c);
     40     link(y,x,!c);
     41     pushup(y);
     42 }
     43 
     44 inline void splay(int x)
     45 {
     46     while(!isroot(x))
     47     {
     48         int y=fa[x];
     49         int cy=(son[fa[y]][1]==y),cx=(son[y][1]==x);
     50         if(isroot(y)) rotate(x,cx);
     51         else
     52         {
     53             if(cx==cy) rotate(y,cy);
     54             else rotate(x,cx);
     55             rotate(x,cy);
     56         }
     57     }
     58     pushup(x);
     59 }
     60 
     61 inline int access(int x)
     62 {
     63     int y;
     64     for(y=0;x;y=x,x=fa[x])
     65     {
     66         splay(x);
     67         son[x][1]=y;
     68         pushup(x);
     69     }
     70     return y;
     71 }
     72 
     73 inline int querysum(int x,int y)
     74 {
     75     access(x);
     76     int lca=access(y);
     77     splay(x);
     78     if(lca==x) return val[lca]+sum[son[lca][1]];
     79     else return val[lca]+sum[son[lca][1]]+sum[x];
     80 }
     81 
     82 inline int querymax(int x,int y)
     83 {
     84     access(x);
     85     int lca=access(y);
     86     splay(x);
     87     if(lca==x) return max(val[lca],mx[son[lca][1]]);
     88     else return max(val[lca],max(mx[son[lca][1]],mx[x]));
     89 }
     90 
     91 inline void change(int x,int w)
     92 {
     93     //access(x);
     94     splay(x); val[x]=w; pushup(x);
     95 }
     96 
     97 inline void add(int u,int v)
     98 {
     99     to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
    100 }
    101 
    102 inline void bfs()
    103 {
    104     memset(vis,0,sizeof vis);
    105     vis[1]=true; q[1]=1;
    106     int h=1,t=2,sta;
    107     while(h<t)
    108     {
    109         sta=q[h++];
    110         for(int i=head[sta];~i;i=next[i])
    111             if(!vis[to[i]])
    112             {
    113                 fa[to[i]]=sta;
    114                 vis[to[i]]=true;
    115                 q[t++]=to[i];
    116             }
    117     }
    118 }
    119 
    120 inline void go()
    121 {
    122     memset(head,-1,sizeof head); cnt=0;
    123     memset(son,0,sizeof son);
    124     memset(fa,0,sizeof fa);
    125     mx[0]=-INF;
    126     scanf("%d",&n);
    127     for(int i=1,a,b;i<n;i++)
    128     {
    129         scanf("%d%d",&a,&b);
    130         add(a,b); add(b,a);
    131     }
    132     for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    133     bfs();
    134     scanf("%d",&m);
    135     char str[10]; int a,b;
    136     while(m--)
    137     {
    138         scanf("%s",str);
    139         scanf("%d%d",&a,&b);
    140         if(str[1]=='H') change(a,b);
    141         else if(str[1]=='S') printf("%d\n",querysum(a,b));
    142         else printf("%d\n",querymax(a,b));
    143     }
    144 }
    145 
    146 int main()
    147 {
    148     go();
    149     return 0;
    150 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    HDOJ 2689
    UVALive 3635 Pie 切糕大师 二分
    黑马程序员 Java基础<十八>---> 网路编程
    C# 数据库dataGridView刷新数据和主外键判断
    影视-纪录片:《生死洄游》
    汉语-词语:旅行
    汉语-词语:探险
    风水学:龙脉
    人物-探险家:斯文·赫定
    影视-纪录片:《河西走廊之嘉峪关》
  • 原文地址:https://www.cnblogs.com/proverbs/p/2845053.html
Copyright © 2011-2022 走看看