hdu 4010 Query on the trees LCT

 

维护一个带点权的无向图森林,支持:

  1、删边

  2、加边

  3、增加某条链所有点的点权

  4、求某条链上点权的最大值

 

大概思路:

前两个需要更改根(即需要翻转标记)

第三个又需要一个标记,第四个每个节点记录该splay中以该节点为根的子树的最大点权。

 

收获:

  1、对于splay前的标记下传可用递归写法, 虽然慢一点,但不容易写错。

  2、access的过程中,在边转换完成后要更新节点信息。

  3、对于寻找某子树的根,可以一直向上(会途径重边和轻边)找,这样比access+splay快很多,也很好写。

  4、标记的意义是:”我想要对这个节点的子节点操作,但不是现在“,即标记只代表需要对子节点操作而不代表需要对当前节点操作,所以在加标记时,要确保当前节点已经应用了该种操作。

 

  1 #include <cstdio>
  2 #include <iostream>
  3 #define fprintf(...)
  4 #define maxn 300010
  5 using namespace std;
  6 
  7 struct LCT {
  8     int pnt[maxn], pre[maxn], son[maxn][2];
  9     int val[maxn], maxv[maxn], rtag[maxn], itag[maxn];
 10 
 11     void update( int nd ) {
 12         maxv[nd] = max( val[nd], max(maxv[son[nd][0]],maxv[son[nd][1]]) );
 13     }
 14     void rotate( int nd, int d ) {
 15         int p = pre[nd];
 16         int s = son[nd][!d];
 17         int ss = son[s][d];
 18 
 19         son[nd][!d] = ss;
 20         son[s][d] = nd;
 21         if( p ) son[p][ nd==son[p][1] ] = s;
 22         else pnt[s] = pnt[nd];
 23 
 24         pre[nd] = s;
 25         pre[s] = p;
 26         pre[ss] = nd;
 27 
 28         update( nd );
 29         update( s );
 30     }
 31     void pushdown( int nd ) {
 32         if( rtag[nd] ) {
 33             int &ls = son[nd][0], &rs = son[nd][1];
 34             swap( ls, rs );
 35             rtag[ls] ^= 1;
 36             rtag[rs] ^= 1;
 37             rtag[nd] = 0;
 38         } 
 39         if( itag[nd] ) {
 40             int ls = son[nd][0], rs = son[nd][1];
 41             int delta = itag[nd];
 42             itag[ls] += delta;
 43             itag[rs] += delta;
 44             if( ls ) val[ls]  += delta;
 45             if( rs ) val[rs]  += delta;
 46             if( ls ) maxv[ls] += delta;
 47             if( rs ) maxv[rs] += delta;
 48             itag[nd] = 0;
 49         }
 50     }
 51     void big_push( int nd ) {
 52         if( pre[nd] ) big_push(pre[nd]);
 53         pushdown(nd);
 54     }
 55     void splay( int nd, int top=0 ) {
 56         big_push( nd );
 57         while( pre[nd]!=top ) {
 58             int p = pre[nd];
 59             int nl = nd==son[p][0];
 60             if( pre[p]==top ) {
 61                 rotate( p, nl );
 62             } else {
 63                 int pp = pre[p];
 64                 int pl = p==son[pp][0];
 65                 if( nl==pl ) {
 66                     rotate( pp, pl );
 67                     rotate( p, nl );
 68                 } else {
 69                     rotate( p, nl );
 70                     rotate( pp, pl );
 71                 }
 72             }
 73         }
 74     }
 75     void access( int nd ) {
 76         int u = nd;
 77         int v = 0;
 78         while( u ) {
 79             splay( u );
 80             int s = son[u][1];
 81             pre[s] = 0;
 82             pnt[s] = u;
 83             pre[v] = u;
 84             son[u][1] = v;
 85             update( u );
 86             v = u;
 87             u = pnt[u];
 88         }
 89         splay(nd);
 90     }
 91     void init( int n ) {
 92         for( int i=0; i<=n; i++ )
 93             pnt[i] = pre[i] = son[i][0] = son[i][1] = val[i] 
 94                 = maxv[i] = rtag[i] = itag[i] = 0;
 95     }
 96     void makeroot( int nd ) {
 97         access(nd);
 98         rtag[nd] = true;
 99     }
100     void link( int u, int v ) {
101         makeroot(u);
102         makeroot(v);
103         pnt[u] = v;
104     }
105     void cut( int rt, int u ) {
106         makeroot(rt);
107         access(u);
108         int ls = son[u][0];
109         pre[ls] = 0;
110         pnt[ls] = pnt[u];
111         pnt[u] = 0;
112         son[u][0] = 0;
113     }
114     void modify( int nd, int w ) {
115         splay(nd);
116         val[nd] = w;
117         update(nd);
118     }
119     int findroot( int u ) {
120         while( pre[u] ) 
121             u = pre[u];
122         while( pnt[u] ) {
123             u = pnt[u];
124             while( pre[u] ) u=pre[u];
125         }
126         return u;
127     }
128     inline bool sameroot( int u, int v ) {
129         return findroot(u)==findroot(v);
130     }
131     void inc_val( int u, int v, int w ) {
132         makeroot(u);
133         access(v);
134         val[v] += w;
135         maxv[v] += w;
136         itag[v] += w;
137     }
138     int qu_max( int u, int v ) {
139         makeroot(u);
140         access(v);
141         return maxv[v];
142     }
143 };
144 
145 int n, q;
146 LCT LT;
147 
148 int main() {
149     while(1) {
150         if( scanf( "%d", &n )!=1 ) return 0;
151         LT.init(n);
152         for( int i=1,u,v; i<n; i++ ) {
153             scanf( "%d%d", &u, &v );
154             LT.link(u,v);
155         }
156         for( int i=1,w; i<=n; i++ ) {
157             scanf( "%d", &w );
158             LT.modify( i, w );
159         }
160         scanf( "%d", &q );
161         for( int i=1; i<=q; i++ ) {
162             int opt, x, y, w;
163             scanf( "%d", &opt );
164             if( opt==1 ) {
165                 scanf( "%d%d", &x, &y );
166                 if( LT.sameroot(x,y) ) 
167                     printf( "-1\n" );
168                 else 
169                     LT.link(x,y);
170             } else if( opt==2 ) {
171                 scanf( "%d%d", &x, &y );
172                 if( x==y || !LT.sameroot(x,y) ) 
173                     printf( "-1\n" );
174                 else 
175                     LT.cut( x, y );
176             } else if( opt==3 ) {
177                 scanf( "%d%d%d", &w, &x, &y );
178                 if( !LT.sameroot(x,y) ) 
179                     printf( "-1\n" );
180                 else 
181                     LT.inc_val( x, y, w );
182             } else {
183                 scanf( "%d%d", &x, &y );
184                 if( !LT.sameroot(x,y) ) 
185                     printf( "-1\n" );
186                 else 
187                     printf( "%d\n", LT.qu_max( x, y ) );
188             }
189         }
190         printf( "\n" );
191     }
192 }
View Code

 

posted @ 2015-02-13 22:41  idy002  阅读(116)  评论(0编辑  收藏  举报