连猫树
Link Cat Tree
link-cat-tree,即为所谓的连猫树是也!
我们需要先学习树剖 & splay
然后就发现,我去这个splay好TM短啊,只剩两个函数了.....节哀......
仔细思考ass♂ass♂in函数,然后发现lct也不过如此,好像很容易理解。
然后我模板就打了两天才搞好......
注意splay中维护的key是深度,一个splay表示一条竖着的链。
判断根有些变化了...相应的有些写法也要改变。
可以看代码里的注释。
1 #include <cstdio> 2 #include <algorithm> 3 const int N = 300010; 4 inline void read(int &x) { 5 x = 0; 6 char c = getchar(); 7 while(c < '0' || c > '9') { 8 c = getchar(); 9 } 10 while(c >= '0' && c <= '9') { 11 x = (x << 3) + (x << 1) + c - 48; 12 c = getchar(); 13 } 14 return; 15 } 16 int val[N]; 17 18 struct LCT { 19 int fa[N], s[N][2], sum[N], stk[N], top; 20 bool rev[N]; 21 22 inline void pushup(int x) { 23 sum[x] = val[x] ^ sum[s[x][0]] ^ sum[s[x][1]]; 24 return; 25 } 26 inline void pushdown(int x) { 27 if(rev[x]) { 28 std::swap(s[x][1], s[x][0]); 29 if(s[x][1]) { 30 rev[s[x][1]] ^= 1; 31 } 32 if(s[x][0]) { 33 rev[s[x][0]] ^= 1; 34 } 35 rev[x] = 0; /// 别忘了 36 } 37 return; 38 } 39 inline bool no_root(int x) { 40 return s[fa[x]][0] == x || s[fa[x]][1] == x; 41 } 42 inline void rotate(int x) { 43 int y = fa[x]; 44 int z = fa[y]; 45 bool f = (s[y][1] == x); 46 47 if(no_root(y)) { 48 s[z][s[z][1] == y] = x; 49 } 50 fa[x] = z; 51 s[y][f] = s[x][!f]; 52 fa[s[x][!f]] = y; 53 s[x][!f] = y; 54 fa[y] = x; 55 56 pushup(y);/// 虽然不用down了但是up还是有必要的 57 pushup(x); 58 return; 59 } 60 inline void splay(int x) { 61 top = 0; 62 stk[++top] = x; 63 for(int i = x; no_root(i); i = fa[i]) { 64 stk[++top] = fa[i]; /// 预先下放标记 65 } 66 for(int i = top; i; i--) { 67 pushdown(stk[i]); 68 } 69 int y = fa[x]; 70 int z = fa[y]; 71 while(no_root(x)) { 72 if(no_root(y)) { 73 (s[z][1] == y) ^ (s[y][1] == x) ? 74 rotate(x) : rotate(y); 75 } 76 rotate(x); 77 y = fa[x]; 78 z = fa[y]; 79 } 80 return; 81 } 82 inline void access(int x) { 83 int y = 0; 84 while(x) { 85 splay(x); 86 s[x][1] = y; 87 pushup(x); /// s[1]变了所以要up 88 y = x; 89 x = fa[x]; 90 } 91 return; 92 } 93 inline int findroot(int x) { 94 access(x); 95 splay(x); 96 pushdown(x);/// 这个很重要 97 while(s[x][0]) { 98 x = s[x][0]; 99 pushdown(x); /// 同上 100 } 101 return x; 102 } 103 inline void makeroot(int x) { 104 access(x); 105 splay(x); 106 rev[x] = 1; 107 //pushdown(x); 此处可以不加 108 return; 109 } 110 inline void link(int x, int y) { 111 makeroot(x); 112 if(findroot(y) != x) { 113 fa[x] = y; 114 } 115 return; 116 } 117 inline void cut(int x, int y) { 118 makeroot(x); 119 access(y); 120 splay(y); 121 if(!s[x][1] && fa[x] == y && s[y][0] == x) { 122 fa[x] = s[y][0] = 0; /// 注意三个条件和up 123 pushup(y); 124 } 125 return; 126 } 127 inline void change(int x, int a) { 128 makeroot(x); 129 val[x] = a; 130 pushup(x); 131 return; 132 } 133 inline int ask(int x, int y) { 134 makeroot(x); 135 access(y); 136 splay(y); 137 return sum[y]; 138 } 139 }lct; 140 141 int main() { 142 int m, n, f, x, y; 143 read(n); 144 read(m); 145 for(int i = 1; i <= n; i++) { 146 read(val[i]); 147 } 148 while(m--) { 149 read(f); 150 read(x); 151 read(y); 152 if(!f) { 153 printf("%d\n", lct.ask(x, y)); 154 } 155 else if(f == 1) { 156 lct.link(x, y); 157 } 158 else if(f == 2) { 159 lct.cut(x, y); 160 } 161 else { 162 lct.change(x, y); 163 } 164 } 165 return 0; 166 }
还有个水一点的题:
1 #include <cstdio> 2 #include <algorithm> 3 const int N = 10010; 4 5 struct LinkCutTree { 6 int fa[N], s[N][2], top, stk[N]; 7 bool rev[N]; 8 9 inline void pushdown(int x) { 10 if(rev[x]) { 11 std::swap(s[x][0], s[x][1]); 12 if(s[x][0]) { 13 rev[s[x][0]] ^= 1; 14 } 15 if(s[x][1]) { 16 rev[s[x][1]] ^= 1; 17 } 18 rev[x] = 0; 19 } 20 return; 21 } 22 inline bool no_root(int x) { 23 return s[fa[x]][0] == x || s[fa[x]][1] == x; 24 } 25 inline void rotate(int x) { 26 int y = fa[x]; 27 int z = fa[y]; 28 bool f = (s[y][1] == x); 29 30 if(no_root(y)) { 31 s[z][s[z][1] == y] = x; 32 } 33 fa[x] = z; 34 s[y][f] = s[x][!f]; 35 fa[s[x][!f]] = y; 36 s[x][!f] = y;; 37 fa[y] = x; 38 39 return; 40 } 41 inline void splay(int x) { 42 top = 0; 43 stk[++top] = x; 44 for(int i = x; no_root(i); i = fa[i]) { 45 stk[++top] = fa[i]; 46 } 47 for(; top; top--) { 48 pushdown(stk[top]); 49 } 50 int y = fa[x]; 51 int z = fa[y]; 52 while(no_root(x)) { 53 if(no_root(y)) { 54 (s[z][1] == y) ^ (s[y][1] == x) ? 55 rotate(x) : rotate(y); 56 } 57 rotate(x); 58 y = fa[x]; 59 z = fa[y]; 60 } 61 return; 62 } 63 inline void access(int x) { 64 int y = 0; 65 while(x) { 66 splay(x); 67 s[x][1] = y; 68 y = x; 69 x = fa[x]; 70 } 71 return; 72 } 73 inline int findroot(int x) { 74 access(x); 75 splay(x); 76 while(s[x][0]) { 77 x = s[x][0]; 78 } 79 return x; 80 } 81 inline void makeroot(int x) { 82 access(x); 83 splay(x); 84 rev[x] = 1; 85 return; 86 } 87 inline bool ask(int x, int y) { 88 makeroot(x); 89 return findroot(y) == x; 90 } 91 inline void link(int x, int y) { 92 makeroot(x); 93 if(findroot(y) != x) { 94 fa[x] = y; 95 } 96 return; 97 } 98 inline void cut(int x, int y) { 99 makeroot(x); 100 access(y); 101 splay(y); 102 if(!s[x][1] && s[y][0] == x && fa[x] == y) { 103 fa[x] = s[y][0] = 0; 104 } 105 return; 106 } 107 }lct; 108 109 int main() { 110 int n, m, x, y; 111 char c[20]; 112 scanf("%d%d", &n, &m); 113 while(m--) { 114 scanf("%s", c); 115 scanf("%d%d", &x, &y); 116 if(c[0] == 'Q') { 117 lct.ask(x, y) ? printf("Yes\n") : printf("No\n"); 118 } 119 else if(c[0] == 'C') { 120 lct.link(x, y); 121 } 122 else { 123 lct.cut(x, y); 124 } 125 } 126 return 0; 127 }
看着这短短一百多行代码,再回想普通平衡树的惊人码量......
接下来是一些习题:
洛谷 P3950 部落冲突
俗话说得好,智商不够,数据结构来凑。
虽然标算是树上差分,但是由于我们正在练习LCT......
最后一个点0.9s卡过了。
1 #include <cstdio> 2 #include <algorithm> 3 4 const int N = 300010; 5 6 struct LCT { 7 int fa[N], s[N][2], stk[N], top; 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 inline void pushdown(int x) { 14 if(rev[x]) { 15 std::swap(s[x][0], s[x][1]); 16 if(s[x][0]) { 17 rev[s[x][0]] ^= 1; 18 } 19 if(s[x][1]) { 20 rev[s[x][1]] ^= 1; 21 } 22 rev[x] = 0; 23 } 24 return; 25 } 26 inline void rotate(int x) { 27 int y = fa[x]; 28 int z = fa[y]; 29 bool f = (s[y][1] == x); 30 31 if(no_root(y)) { 32 s[z][s[z][1] == y] = x; 33 } 34 fa[x] = z; 35 s[y][f] = s[x][!f]; 36 fa[s[x][!f]] = y; 37 s[x][!f] = y; 38 fa[y] = x; 39 40 return; 41 } 42 inline void splay(int x) { 43 top = 0; 44 stk[++top] = x; 45 for(int i = x; no_root(i); i = fa[i]) { 46 stk[++top] = fa[i]; 47 } 48 for(int i = top; i; i--) { 49 pushdown(stk[i]); 50 } 51 int y = fa[x]; 52 int z = fa[y]; 53 while(no_root(x)) { 54 if(no_root(y)) { 55 (s[z][1] == y) ^ (s[y][1] == x) ? 56 rotate(x) : rotate(y); 57 } 58 rotate(x); 59 y = fa[x]; 60 z = fa[y]; 61 } 62 return; 63 } 64 inline void access(int x) { 65 int y = 0; 66 while(x) { 67 splay(x); 68 s[x][1] = y; 69 y = x; 70 x = fa[x]; 71 } 72 return; 73 } 74 inline void makeroot(int x) { 75 access(x); 76 splay(x); 77 rev[x] = 1; 78 return; 79 } 80 inline int findroot(int x) { 81 access(x); 82 splay(x); 83 pushdown(x); 84 while(s[x][0]) { 85 x = s[x][0]; 86 pushdown(x); 87 } 88 return x; 89 } 90 inline void link(int x, int y) { 91 makeroot(x); 92 fa[x] = y; 93 return; 94 } 95 inline void cut(int x, int y) { 96 makeroot(x); 97 access(y); 98 splay(y); 99 fa[x] = s[y][0] = 0; 100 return; 101 } 102 inline bool ask(int x, int y) { 103 makeroot(x); 104 return findroot(y) == x; 105 } 106 }lct; 107 108 int A[N], B[N]; 109 110 int main() { 111 int m, n, x, y, num = 0; 112 char c[20]; 113 scanf("%d%d", &n, &m); 114 for(int i = 1; i < n; i++) { 115 scanf("%d%d", &x, &y); 116 lct.link(x, y); 117 } 118 for(int i = 1; i <= m; i++) { 119 scanf("%s", c); 120 scanf("%d", &x); 121 if(c[0] == 'Q') { 122 scanf("%d", &y); 123 lct.ask(x, y) ? printf("Yes\n") : printf("No\n"); 124 } 125 else if(c[0] == 'C') { 126 scanf("%d", &y); 127 A[++num] = x; 128 B[num] = y; 129 lct.cut(x, y); 130 } 131 else { 132 lct.link(A[x], B[x]); 133 } 134 } 135 136 return 0; 137 }