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 }

 

 

你可能感兴趣的:(ZOJ)