维护一个带点权的无向图森林,支持:
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 " ); 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 " ); 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 " ); 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 " ); 186 else 187 printf( "%d ", LT.qu_max( x, y ) ); 188 } 189 } 190 printf( " " ); 191 } 192 }