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 }

 

 

posted @ 2013-01-04 23:58  proverbs  阅读(1253)  评论(0编辑  收藏  举报