连猫树

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 } 
洛谷 P3690 AC代码

还有个水一点的题:

  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 }
SDOI2008 洞穴勘测

看着这短短一百多行代码,再回想普通平衡树的惊人码量......

接下来是一些习题:


洛谷 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 }
AC代码

 

posted @ 2018-07-25 17:43  garage  阅读(166)  评论(1编辑  收藏  举报