UOJ 274 温暖会指引我们前进 - LCT
Solution
更新掉路径上温暖度最小的边就可以了~
Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define ll long long 5 #define rd read() 6 using namespace std; 7 8 const int N = 4e5 + 5; 9 const int inf = ~0U >> 1; 10 11 int n, m, fa[N]; 12 13 struct edge { 14 int u, v, t, w; 15 }e[N]; 16 17 int read() { 18 int X = 0, p = 1; char c = getchar(); 19 for (; c > '9' || c < '0'; c = getchar()) 20 if (c == '-') p = -1; 21 for (; c >= '0' && c <= '9'; c = getchar()) 22 X = X * 10 + c - '0'; 23 return X * p; 24 } 25 26 int anc(int x) { 27 return fa[x] == x ? x : fa[x] = anc(fa[x]); 28 } 29 30 namespace LCT { 31 int f[N], ch[N][2], val[N], mn[N], tun[N]; 32 ll sum[N]; 33 #define lc(x) ch[x][0] 34 #define rc(x) ch[x][1] 35 36 int isroot(int x) { 37 return lc(f[x]) != x && rc(f[x]) != x; 38 } 39 40 int get(int x) { 41 return rc(f[x]) == x; 42 } 43 44 void up(int x) { 45 mn[x] = val[x]; 46 sum[x] = e[val[x]].t; 47 if (e[mn[lc(x)]].w < e[mn[x]].w) mn[x] = mn[lc(x)]; 48 if (e[mn[rc(x)]].w < e[mn[x]].w) mn[x] = mn[rc(x)]; 49 if (lc(x)) sum[x] += sum[lc(x)]; 50 if (rc(x)) sum[x] += sum[rc(x)]; 51 } 52 53 void rev(int x) { 54 swap(lc(x), rc(x)); 55 tun[x] ^= 1; 56 } 57 58 void pushdown(int x) { 59 if (tun[x]) { 60 if (lc(x)) rev(lc(x)); 61 if (rc(x)) rev(rc(x)); 62 tun[x] = 0; 63 } 64 } 65 66 int st[N], tp; 67 68 void pd(int x) { 69 while (!isroot(x)) { 70 st[++tp] = x; 71 x = f[x]; 72 } 73 pushdown(x); 74 while (tp) pushdown(st[tp--]); 75 } 76 77 void rotate(int x) { 78 int old = f[x], oldf = f[old], son = ch[x][get(x) ^ 1]; 79 if (!isroot(old)) ch[oldf][get(old)] = x; 80 ch[x][get(x) ^ 1] = old; 81 ch[old][get(x)] = son; 82 f[old] = x; f[x] = oldf; f[son] = old; 83 up(old); up(x); 84 } 85 86 void splay(int x) { 87 pd(x); 88 for (; !isroot(x); rotate(x)) 89 if (!isroot(f[x])) 90 rotate(get(f[x]) == get(x) ? f[x] : x); 91 } 92 93 void access(int x) { 94 for (int y = 0; x; y = x, x = f[x]) 95 splay(x), ch[x][1] = y, up(x); 96 } 97 98 int findr(int x) { 99 access(x); splay(x); 100 while (lc(x)) pushdown(x), x = lc(x); 101 return x; 102 } 103 104 void mroot(int x) { 105 access(x); splay(x); rev(x); 106 } 107 108 void split(int x, int y) { 109 mroot(x); access(y); splay(y); 110 } 111 112 void link(int x, int y) { 113 mroot(x); 114 f[x] = y; 115 } 116 117 void cut(int x, int y) { 118 split(x, y); 119 f[x] = ch[y][0] = 0; 120 } 121 } 122 using namespace LCT; 123 124 int main() 125 { 126 e[0].w = inf; 127 n = rd; m = rd; 128 for (int i = 1; i <= n; ++i) 129 fa[i] = i; 130 for (int i = 1; i <= m; ++i) 131 val[i + n] = i; 132 char op[10]; 133 for (int i = 1; i <= m; ++i) { 134 scanf("%s", op); 135 if (op[0] == 'f') { 136 int id = rd + 1; 137 e[id].u = rd + 1; 138 e[id].v = rd + 1; 139 e[id].w = rd; 140 e[id].t = rd; 141 int x = e[id].u, y = e[id].v; 142 if (anc(x) != anc(y)) { 143 link(id + n, x); 144 link(id + n, y); 145 x = anc(x); y = anc(y); 146 fa[x] = y; 147 } 148 else { 149 split(x, y); 150 int t = mn[y]; 151 if (e[id].w < e[t].w) 152 continue; 153 cut(t + n, e[t].u); 154 cut(t + n, e[t].v); 155 link(id + n, e[id].u); 156 link(id + n, e[id].v); 157 } 158 } 159 else if(op[0] == 'm') { 160 int x = rd + 1, y = rd + 1; 161 if (anc(x) != anc(y)) { 162 puts("-1"); continue; 163 } 164 if (x == y) {puts("0"); continue;} 165 split(x, y); 166 printf("%lld\n", sum[y]); 167 } 168 else { 169 int id = rd + 1; 170 e[id].t = rd; 171 mroot(id + n); 172 } 173 } 174 }