动态树,支持加边,修改点权,查询链的点权和。
1 #include <cstdio> 2 #include <iostream> 3 #define maxn 30010 4 using namespace std; 5 6 namespace L { 7 int pnt[maxn], pre[maxn], son[maxn][2], val[maxn], sum[maxn], rtg[maxn]; 8 9 void update( int nd ) { 10 sum[nd] = val[nd] + sum[son[nd][0]] + sum[son[nd][1]]; 11 } 12 void rotate( int nd, int d ) { 13 int p = pre[nd]; 14 int s = son[nd][!d]; 15 int ss = son[s][d]; 16 son[nd][!d] = ss; 17 son[s][d] = nd; 18 if( p ) son[p][ nd==son[p][1] ] = s; 19 else pnt[s] = pnt[nd]; 20 pre[nd] = s; 21 pre[s] = p; 22 pre[ss] = nd; 23 update( nd ); 24 update( s ); 25 } 26 void pushdown( int nd ) { 27 if( rtg[nd] ) { 28 int &ls = son[nd][0], &rs = son[nd][1]; 29 swap(ls,rs); 30 rtg[ls] ^= 1; 31 rtg[rs] ^= 1; 32 rtg[nd] = 0; 33 } 34 } 35 void big_push( int nd ) { 36 if( pre[nd] ) big_push(pre[nd]); 37 pushdown(nd); 38 } 39 void splay( int nd, int top=0 ) { 40 big_push(nd); 41 while( pre[nd]!=top ) { 42 int p = pre[nd]; 43 int nl = nd==son[p][0]; 44 if( pre[p]==top ) { 45 rotate( p, nl ); 46 } else { 47 int pp = pre[p]; 48 int pl = p==son[pp][0]; 49 if( nl==pl ) { 50 rotate( pp, pl ); 51 rotate( p, nl ); 52 } else { 53 rotate( p, nl ); 54 rotate( pp, pl ); 55 } 56 } 57 } 58 } 59 void access( int nd ) { 60 int u = nd; 61 int v = 0; 62 while( u ) { 63 splay( u ); 64 int s = son[u][1]; 65 pre[s] = 0; 66 pnt[s] = u; 67 pre[v] = u; 68 son[u][1] = v; 69 update( u ); 70 v = u; 71 u = pnt[u]; 72 } 73 splay(nd); 74 } 75 void makeroot( int nd ) { 76 access(nd); 77 rtg[nd] ^= 1; 78 } 79 int findroot( int nd ) { 80 while( pre[nd] ) nd=pre[nd]; 81 while( pnt[nd] ) { 82 nd = pnt[nd]; 83 while( pre[nd] ) nd=pre[nd]; 84 } 85 return nd; 86 } 87 bool sameroot( int u, int v ) { 88 return findroot(u)==findroot(v); 89 } 90 void link( int u, int v ) { 91 makeroot(u); 92 makeroot(v); 93 pnt[u] = v; 94 } 95 void up_val( int nd, int v ) { 96 splay( nd ); 97 val[nd] = v; 98 update( nd ); 99 } 100 int qu_sum( int u, int v ) { 101 makeroot(u); 102 access(v); 103 return val[v]+sum[son[v][0]]; 104 } 105 }; 106 107 int n, q; 108 109 int main() { 110 scanf( "%d", &n ); 111 for( int i=1, w; i<=n; i++ ) { 112 scanf( "%d", &w ); 113 L::up_val( i, w ); 114 } 115 scanf( "%d", &q ); 116 while( q-- ) { 117 char ch[100]; 118 int u, v, w; 119 scanf( "%s", ch ); 120 if( ch[0]=='b' ) { 121 scanf( "%d%d", &u, &v ); 122 if( L::sameroot(u,v) ) printf( "no " ); 123 else { 124 printf( "yes " ); 125 L::link(u,v); 126 } 127 } else if( ch[0]=='p' ) { 128 scanf( "%d%d", &u, &w ); 129 L::up_val( u, w ); 130 } else { 131 scanf( "%d%d", &u, &v ); 132 if( L::sameroot(u,v) ) 133 printf( "%d ", L::qu_sum(u,v) ); 134 else 135 printf( "impossible " ); 136 } 137 } 138 }