洛谷P4219 大融合
LCT新姿势:维护子树信息。
不能带修,子树修改就要toptree了...
题意:动态加边,求子树大小。
解:
维护子树信息只要额外维护虚边连的儿子的信息即可。这里把siz的定义变成子树大小。
哪里会修改虚边呢?link和access。把这两个函数改一改就行了。
注意这里link的时候x和y都要make_root,因为修改只能修改根。
1 #include <cstdio> 2 #include <algorithm> 3 4 typedef long long LL; 5 const int N = 100010; 6 7 int fa[N], s[N][2], sum[N], val[N], S[N], Sp; 8 bool rev[N]; 9 10 inline bool no_root(int x) { 11 return (s[fa[x]][0] == x) || (s[fa[x]][1] == x); 12 } 13 14 inline void pushup(int x) { 15 sum[x] = sum[s[x][0]] + sum[s[x][1]] + val[x]; 16 return; 17 } 18 19 inline void pushdown(int x) { 20 if(rev[x]) { 21 if(s[x][0]) { 22 rev[s[x][0]] ^= 1; 23 } 24 if(s[x][1]) { 25 rev[s[x][1]] ^= 1; 26 } 27 std::swap(s[x][0], s[x][1]); 28 rev[x] = 0; 29 } 30 return; 31 } 32 33 inline void rotate(int x) { 34 int y = fa[x]; 35 int z = fa[y]; 36 bool f = (s[y][1] == x); 37 38 fa[x] = z; 39 if(no_root(y)) { 40 s[z][s[z][1] == y] = x; 41 } 42 s[y][f] = s[x][!f]; 43 if(s[x][!f]) { 44 fa[s[x][!f]] = y; 45 } 46 s[x][!f] = y; 47 fa[y] = x; 48 49 pushup(y); 50 pushup(x); 51 return; 52 } 53 54 inline void splay(int x) { 55 int y = x; 56 S[++Sp] = y; 57 while(no_root(y)) { 58 y = fa[y]; 59 S[++Sp] = y; 60 } 61 while(Sp) { 62 pushdown(S[Sp]); 63 Sp--; 64 } 65 66 y = fa[x]; 67 int z = fa[y]; 68 while(no_root(x)) { 69 if(no_root(y)) { 70 (s[z][1] == y) ^ (s[y][1] == x) ? 71 rotate(x) : rotate(y); 72 } 73 rotate(x); 74 y = fa[x]; 75 z = fa[y]; 76 } 77 return; 78 } 79 80 inline void access(int x) { 81 int y = 0; 82 while(x) { 83 splay(x); 84 val[x] += sum[s[x][1]] - sum[y]; 85 s[x][1] = y; 86 pushup(x); 87 y = x; 88 x = fa[x]; 89 } 90 return; 91 } 92 93 inline void make_root(int x) { 94 access(x); 95 splay(x); 96 rev[x] = 1; 97 return; 98 } 99 100 inline void link(int x, int y) { 101 make_root(x); 102 make_root(y); 103 fa[x] = y; 104 val[y] += sum[x]; 105 sum[y] += sum[x]; 106 return; 107 } 108 109 inline int ask(int x, int r) { 110 make_root(x); 111 access(r); 112 splay(r); 113 return sum[x]; 114 } 115 116 char str[20]; 117 118 int main() { 119 int n, q; 120 scanf("%d%d", &n, &q); 121 for(int i = 1; i <= n; i++) { 122 val[i] = 1; 123 } 124 for(int i = 1, x, y; i <= q; i++) { 125 scanf("%s%d%d", str, &x, &y); 126 if(str[0] == 'A') { 127 link(x, y); 128 } 129 else { 130 int t = ask(x, y); 131 int tt = ask(y, x); 132 printf("%lld\n", 1ll * t * tt); 133 } 134 } 135 136 return 0; 137 }