lct

以前寫的博客html

嗯,從新寫了個模板出來。網絡

  1 #include <cstdio>
  2 #include <algorithm>
  3 
  4 const int N = 300010;
  5 
  6 int fa[N], s[N][2], val[N], sum[N], S[N], Sp;
  7 bool rev[N];
  8 
  9 inline bool no_root(int x) {
 10     return (s[fa[x]][0] == x) || (s[fa[x]][1] == x);
 11 }
 12 
 13 inline void pushup(int x) {
 14     sum[x] = val[x] ^ sum[s[x][0]] ^ sum[s[x][1]];
 15     return;
 16 }
 17 
 18 inline void pushdown(int x) {
 19     if(rev[x]) {
 20         if(s[x][0]) {
 21             rev[s[x][0]] ^= 1;
 22         }
 23         if(s[x][1]) {
 24             rev[s[x][1]] ^= 1;
 25         }
 26         std::swap(s[x][0], s[x][1]);
 27         rev[x] = 0;
 28     }
 29     return;
 30 }
 31 
 32 inline void rotate(int x) {
 33     int y = fa[x];
 34     int z = fa[y];
 35     bool f = (s[y][1] == x);
 36 
 37     fa[x] = z;
 38     if(no_root(y)) {
 39         s[z][s[z][1] == y] = x;
 40     }
 41     s[y][f] = s[x][!f];
 42     if(s[x][!f]) {
 43         fa[s[x][!f]] = y;
 44     }
 45     s[x][!f] = y;
 46     fa[y] = x;
 47 
 48     pushup(y);
 49     pushup(x);
 50     return;
 51 }
 52 
 53 inline void splay(int x) {
 54     int y = x;
 55     S[++Sp] = y;
 56     while(no_root(y)) {
 57         y = fa[y];
 58         S[++Sp] = y;
 59     }
 60     while(Sp) {
 61         pushdown(S[Sp]);
 62         Sp--;
 63     }
 64 
 65     y = fa[x];
 66     int z = fa[y];
 67     while(no_root(x)) {
 68         if(no_root(y)) {
 69             (s[z][1] == y) ^ (s[y][1] == x) ?
 70             rotate(x) : rotate(y);
 71         }
 72         rotate(x);
 73         y = fa[x];
 74         z = fa[y];
 75     }
 76     return;
 77 }
 78 
 79 inline void access(int x) {
 80     int y = 0;
 81     while(x) {
 82         splay(x);
 83         s[x][1] = y;
 84         /*if(y) {
 85             fa[y] = x; // no need change fa[y] 
 86         }*/
 87         pushup(x);
 88         y = x;
 89         x = fa[x];
 90     }
 91     return;
 92 }
 93 
 94 inline void make_root(int x) {
 95     access(x);
 96     splay(x);
 97     rev[x] ^= 1;
 98     return;
 99 }
100 
101 inline int find_root(int x) {
102     access(x);
103     splay(x);
104     while(s[x][0]) {
105         x = s[x][0];
106         pushdown(x); // important 
107     }
108     return x;
109 }
110 
111 inline void link(int x, int y) {
112     make_root(x);
113     if(find_root(y) != x) { // cannot change y
114         fa[x] = y;
115     }
116     return;
117 }
118 
119 inline void cut(int x, int y) {
120     make_root(x);
121     access(y);
122     splay(y);
123     if(s[y][0] == x && fa[x] == y && !s[x][1]) {
124         fa[x] = s[y][0] = 0;
125         pushup(y);
126     }
127     return;
128 }
129 
130 inline int ask(int x, int y) {
131     make_root(x);
132     access(y);
133     splay(y);
134     return sum[y];
135 }
136 
137 inline void change(int x, int c) { // only could change the value of root
138     splay(x);
139     val[x] = c;
140     pushup(x);
141     return;
142 }
143 
144 int main() {
145     
146     int n, m;
147     scanf("%d%d", &n, &m);
148     for(int i = 1; i <= n; i++) {
149         scanf("%d", &val[i]);
150     }
151     
152     for(int i = 1, f, x, y; i <= m; i++) {
153         scanf("%d%d%d", &f, &x, &y);
154         if(!f) {
155             int t = ask(x, y);
156             printf("%d\n", t);
157         }
158         else if(f == 1) {
159             link(x, y);
160         }
161         else if(f == 2) {
162             cut(x, y);
163         }
164         else {
165             change(x, y);
166         }
167     }
168     
169     return 0;
170 }
lct模板

有一個小細節:findroot是很特殊的函數。一是它返回int,二是它最後最好加上一句splay(x)。有的題卡這個...ide

以前有個一直困擾個人問題:爲何不能在rotate內pushdown?現已解決。函數

問題出在這種語句上:spa

make_root(x);
access(x);

咱們的目的是把x單獨拿出來做爲一顆splay,可是事實上發生了什麼呢?code

首先你在make_root中access(x)並把它旋到根打標記。此時它有個左兒子和一個標記。htm

而後咱們看,若是咱們access它,那麼第一步是splay它,第二步剪斷它的右兒子。blog

splay的時候,若是咱們把pushdown放在rotate裏面,那麼就一次都不會被執行。在外面就會被執行。get

而後若是沒有執行的話,剪斷右兒子就沒剪掉,由於你右兒子還在左邊。博客

解決方法是在access裏面添加一個pushdown,以後實測AC。

  1 #include <cstdio>
  2 #include <algorithm>
  3 
  4 const int N = 300010;
  5 
  6 int fa[N], s[N][2], val[N], sum[N], S[N], Sp;
  7 bool rev[N];
  8 
  9 inline bool no_root(int x) {
 10     return (s[fa[x]][0] == x) || (s[fa[x]][1] == x);
 11 }
 12 
 13 inline void pushup(int x) {
 14     sum[x] = val[x] ^ sum[s[x][0]] ^ sum[s[x][1]];
 15     return;
 16 }
 17 
 18 inline void pushdown(int x) {
 19     if(rev[x]) {
 20         if(s[x][0]) {
 21             rev[s[x][0]] ^= 1;
 22         }
 23         if(s[x][1]) {
 24             rev[s[x][1]] ^= 1;
 25         }
 26         std::swap(s[x][0], s[x][1]);
 27         rev[x] = 0;
 28     }
 29     return;
 30 }
 31 
 32 inline void rotate(int x) {
 33     int y = fa[x];
 34     int z = fa[y];
 35     pushdown(y);
 36     pushdown(x);
 37     bool f = (s[y][1] == x);
 38 
 39     fa[x] = z;
 40     if(no_root(y)) {
 41         s[z][s[z][1] == y] = x;
 42     }
 43     s[y][f] = s[x][!f];
 44     if(s[x][!f]) {
 45         fa[s[x][!f]] = y;
 46     }
 47     s[x][!f] = y;
 48     fa[y] = x;
 49 
 50     pushup(y);
 51     pushup(x);
 52     return;
 53 }
 54 
 55 inline void splay(int x) {
 56     /*int y = x;
 57     S[++Sp] = y;
 58     while(no_root(y)) {
 59         y = fa[y];
 60         S[++Sp] = y;
 61     }
 62     while(Sp) {
 63         pushdown(S[Sp]);
 64         Sp--;
 65     }*/
 66 
 67     int y = fa[x];
 68     int z = fa[y];
 69     while(no_root(x)) {
 70         if(no_root(y)) {
 71             (s[z][1] == y) ^ (s[y][1] == x) ?
 72             rotate(x) : rotate(y);
 73         }
 74         rotate(x);
 75         y = fa[x];
 76         z = fa[y];
 77     }
 78     return;
 79 }
 80 
 81 inline void access(int x) {
 82     int y = 0;
 83     while(x) {
 84         splay(x);
 85         pushdown(x);
 86         s[x][1] = y; // no need change fa[y]
 87         pushup(x);
 88         y = x;
 89         x = fa[x];
 90     }
 91     return;
 92 }
 93 
 94 inline void make_root(int x) {
 95     access(x);
 96     splay(x);
 97     rev[x] ^= 1;
 98     return;
 99 }
100 
101 inline int find_root(int x) {
102     access(x);
103     splay(x);
104     while(s[x][0]) {
105         x = s[x][0];
106         pushdown(x);
107     }
108     return x;
109 }
110 
111 inline void link(int x, int y) {
112     make_root(x);
113     if(find_root(y) != x) { // cannot change y
114         fa[x] = y;
115     }
116     return;
117 }
118 
119 inline void cut(int x, int y) {
120     make_root(x);
121     access(y);
122     splay(y);
123     if(s[y][0] == x && fa[x] == y && !s[x][1]) {
124         fa[x] = s[y][0] = 0;
125         pushup(y);
126     }
127     return;
128 }
129 
130 inline int ask(int x, int y) {
131     make_root(x);
132     access(y);
133     splay(y);
134     return sum[y];
135 }
136 
137 inline void change(int x, int c) { // change must in root
138     make_root(x);
139     val[x] = c;
140     pushup(x);
141     return;
142 }
143 
144 int main() {
145 
146     int n, m;
147     scanf("%d%d", &n, &m);
148     for(int i = 1; i <= n; i++) {
149         scanf("%d", &val[i]);
150     }
151     for(int i = 1, f, x, y; i <= m; i++) {
152         scanf("%d%d%d", &f, &x, &y);
153         if(!f) {
154             int t = ask(x, y);
155             printf("%d\n", t);
156         }
157         else if(f == 1) {
158             link(x, y);
159         }
160         else if(f == 2) {
161             cut(x, y);
162         }
163         else {
164             change(x, y);
165         }
166     }
167     
168     return 0;
169 }
AC代碼

例題:

洞穴勘測  魔法森林  彈飛綿羊  [ZJOI2012]網絡   Tree II(LONG_MAX0.5 == 46341)

水管局長  溫暖會指引咱們前行  染色   長跑   大融合  在美妙的數學王國中暢遊

僞裝搞完了LCT...總結一波。

不要忘了pushup,rotate別寫錯。能夠維護連通性,生成樹,邊雙,子樹信息。能夠鏈修改。

這纔是基礎模型...神仙題我都作不來...

相關文章
相關標籤/搜索