1. 程式人生 > >[ZJOI2016]大森林

[ZJOI2016]大森林

(貌似整個程式碼不能用 $makeroot$ ?是因為是有根樹?)

因為是區間操作,所以可以考慮在區間內與區間外的差異

對於操作 $1$ ,可以看作一個生成節點包含了到下一個 $1$ 操作之間長出的節點,那麼對於一個操作 $l, r$ ,相當於是在 $l$ 處將當前生成節點及其包含的節點整個移植到它更改後的位置,到 $r + 1$ 時再移植回去,所以可以考慮將一個 $1$ 操作分解為兩個操作(一個移植,一個移植回去),故可以將所有操作按端點、時間排序(以及同位置修改操作必定在查詢操作前,因為可以先把樹建完再查詢對結果沒有影響),掃描一遍即可

同時,為了方便移植,將每個生成節點看作新建的一個虛點

對於操作 $0$ ,直接在虛點下 $link$ 即可,因為就算已經建了一些對於當前操作不存在的虛點,也不會對答案造成影響

對於操作 $2$ ,無法正面在 $LCT$ 上算出兩點的距離,故可考慮查分,得到 $Ans = Sum_x + Sum_y - 2 * Sum_{lca}$ ,其中實點貢獻為 $1$ ,虛點貢獻為 $0$

對於求 $LCA$ ,先 $access (y)$ ,再在 $access (x)$ 的時候得到的最後一個跳虛邊的點即是它們的 $LCA$

程式碼

  1 #include <iostream>
  2 #include <cstdio>
  3
#include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7 8 const int MAXN = 3e05 + 10; 9 10 struct QuerySt { 11 int pos, time; 12 int x, y; 13 14 QuerySt () {} 15 QuerySt (int fpos, int ftime, int fx, int fy) : 16 pos (fpos), time (ftime), x (fx), y (fy) {}
17 18 bool operator < (const QuerySt& p) const { 19 return pos == p.pos ? time < p.time : pos < p.pos; 20 } 21 } ; 22 QuerySt Query[MAXN]; 23 int que = 0; 24 25 int N, M; 26 27 int father[MAXN]= {0}; 28 int son[MAXN][2]= {0}; 29 int Sum[MAXN]= {0}, value[MAXN]= {0}; 30 31 int isroot (int p) { 32 return son[father[p]][0] != p && son[father[p]][1] != p; 33 } 34 int sonbel (int p) { 35 return son[father[p]][1] == p; 36 } 37 void pushup (int p) { 38 Sum[p] = Sum[son[p][0]] + Sum[son[p][1]] + value[p]; 39 } 40 void rotate (int p) { 41 int fa = father[p], anc = father[fa]; 42 int s = sonbel (p); 43 son[fa][s] = son[p][s ^ 1]; 44 if (son[fa][s]) 45 father[son[fa][s]] = fa; 46 if (! isroot (fa)) 47 son[anc][sonbel (fa)] = p; 48 father[p] = anc; 49 son[p][s ^ 1] = fa, father[fa] = p; 50 pushup (fa), pushup (p); 51 } 52 void splay (int p) { 53 for (int fa = father[p]; ! isroot (p); rotate (p), fa = father[p]) 54 if (! isroot (fa)) 55 sonbel (p) == sonbel (fa) ? rotate (fa) : rotate (p); 56 } 57 int Access (int p) { 58 int tp = 0; 59 for ( ; p; tp = p, p = father[p]) 60 splay (p), son[p][1] = tp, pushup (p); 61 return tp; 62 } 63 void link (int x, int y) { // 注意此時沒有makeroot所以需要注意是將y連到x下 64 splay (y); 65 father[y] = x; 66 } 67 void cut (int x) { 68 Access (x), splay (x); 69 father[son[x][0]] = 0, son[x][0] = 0; 70 pushup (x); 71 } 72 73 int totq = 0; 74 int ans[MAXN]= {0}; 75 void Solve () { 76 sort (Query + 1, Query + que + 1); 77 for (int i = 1; i <= que; i ++) { 78 int time = Query[i].time; 79 int x = Query[i].x, y = Query[i].y; 80 if (time > 0) { 81 Access (x), splay (x), ans[time] += Sum[x]; 82 int lca = Access (y); 83 splay (y), ans[time] += Sum[y]; 84 Access (lca), splay (lca), ans[time] -= (Sum[lca] << 1); 85 } 86 else 87 cut (x), link (y, x); 88 } 89 } 90 91 int getnum () { 92 int num = 0; 93 char ch = getchar (); 94 95 while (! isdigit (ch)) 96 ch = getchar (); 97 while (isdigit (ch)) 98 num = (num << 3) + (num << 1) + ch - '0', ch = getchar (); 99 100 return num; 101 } 102 103 int ind[MAXN]= {0}; 104 int liml[MAXN], limr[MAXN]; 105 int nodes = 1; 106 int main () { 107 N = getnum (), M = getnum (); 108 int lastr = 1, real = 1; 109 ind[1] = Sum[1] = value[1] = 1, liml[1] = 1, limr[1] = N; 110 link (1, nodes = lastr = 2); 111 for (int i = 1; i <= M; i ++) { 112 int opt = getnum (); 113 if (opt == 0) { 114 int l = getnum (), r = getnum (); 115 link (lastr, ind[++ real] = ++ nodes); 116 value[nodes] = Sum[nodes] = 1; 117 liml[real] = l, limr[real] = r; 118 } 119 else if (opt == 1) { 120 int l = getnum (), r = getnum (), x = getnum (); 121 l = max (l, liml[x]), r = min (r, limr[x]); 122 if (l > r) 123 continue; 124 link (lastr, ++ nodes); 125 Query[++ que] = QuerySt (l, i - M, nodes, ind[x]); // 由nodes離開link向index[x] 126 Query[++ que] = QuerySt (r + 1, i - M, nodes, lastr); 127 lastr = nodes; 128 } 129 else if (opt == 2) { 130 int x = getnum (), u = getnum (), v = getnum (); 131 Query[++ que] = QuerySt (x, ++ totq, ind[u], ind[v]); // 由index[u]到index[v]的距離 132 } 133 } 134 Solve (); 135 for (int i = 1; i <= totq; i ++) 136 printf ("%d\n", ans[i]); 137 138 return 0; 139 } 140 141 /* 142 5 5 143 0 1 5 144 1 2 4 2 145 0 1 4 146 2 1 1 3 147 2 2 1 3 148 */