HDU - 4010 Query on The Trees——Link Cut Tree
阿新 • • 發佈:2018-11-16
LCT模板題,link和cut是基本操作
更新一條鏈(u,v)就是做 mroot(u); access(v); splay(v)操作;然後給v打上標記,splay時上下推即可
求一條鏈(u,v)的最小值,同樣做 mroot(u); access(v); splay(v);然後求v的最小值即可
上述的mroot(u); access(v); splay(v);實際上是提取鏈(u,v),先將u設為所有輔助樹的根節點,然後打通v到根節點的優先鏈,最後把v旋轉到根,v的子樹便是鏈(u,v)
#include <bits/stdc++.h> using namespace std; const int maxn = 300005; int N, Q; int tot, head[maxn]; struct Edge { int to, next; }edges[maxn<<1]; void init_edges() { tot = 0; for (int i = 1; i <= N; i++) head[i] = -1; } void addedge(int u, int v) { edges[tot].to = v; edges[tot].next = head[u]; head[u] = tot++; } int fa[maxn], ch[maxn][2], val[maxn], maxv[maxn], tag[maxn], rev[maxn], st[maxn]; void init_tree() { for (int i = 0; i <= N; i++) { fa[i] = ch[i][0] = ch[i][1] = val[i] = maxv[i] = tag[i] = rev[i] = 0; } } void dfs(int u) { for (int i = head[u]; ~i; i = edges[i].next) { int v = edges[i].to; if (v == 1 || fa[v]) continue; fa[v] = u; dfs(v); } } bool isroot(int x){ return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x; } void pushup(int x){ int l = ch[x][0], r = ch[x][1]; maxv[x] = max(max(maxv[l], maxv[r]), val[x]); } void pushdown(int x){ int l = ch[x][0], r = ch[x][1]; if (rev[x]) { if (l) rev[l]^=1; if (r) rev[r]^=1; rev[x]^=1; swap(ch[x][0], ch[x][1]); } if (tag[x]) { if (l) { tag[l]+=tag[x]; maxv[l]+=tag[x], val[l]+=tag[x]; } if (r) { tag[r]+=tag[x]; maxv[r]+=tag[x], val[r]+=tag[x]; } tag[x] = 0; } } void rotate(int x){ int y = fa[x], z = fa[y], l, r; if (ch[y][0] == x) l = 0; else l = 1; r = l^1; if (!isroot(y)){ if (ch[z][0] == y) ch[z][0] = x; else ch[z][1] = x; } fa[x] = z; fa[y] = x; fa[ch[x][r]] = y; ch[y][l] = ch[x][r]; ch[x][r] = y; pushup(y); pushup(x); } void splay(int x){ int top = 0; st[++top]=x; for (int i = x; !isroot(i); i = fa[i]) st[++top] = fa[i]; while (top) pushdown(st[top--]); while (!isroot(x)){ int y = fa[x], z = fa[y]; if (!isroot(y)){ if (ch[y][0] == x^ch[z][0] == y) rotate(x); else rotate(y); } rotate(x); } } void access(int x){ int t = 0; while (x) { splay(x); ch[x][1] = t; pushup(x); x = fa[t = x]; } } void mroot(int u){ access(u); splay(u); rev[u] ^= 1; } int find(int u) { access(u); splay(u); while (ch[u][0]) u = ch[u][0]; return u; } bool judge(int u, int v){ return find(u) == find(v); } void link(int u, int v){ mroot(u); fa[u] = v; } void cut(int u, int v){ mroot(u); access(v); splay(v); fa[ch[v][0]] = 0; ch[v][0] = 0; pushup(v); } void update(int u, int v, int w){ mroot(u); access(v); splay(v); tag[v] +=w; maxv[v] += w; val[v] += w; } void query(int u,int v){ mroot(u); access(v); splay(v); printf("%d\n", maxv[v]); } int main() { while (~scanf("%d", &N)) { init_edges(); for (int i = 1; i < N; i++) { int u, v; scanf("%d%d", &u, &v); addedge(u, v); addedge(v, u); } init_tree(); for (int i = 1; i <= N; i++) { scanf("%d", &val[i]); maxv[i] = val[i]; } dfs(1); scanf("%d", &Q); while (Q--) { int opt, u, v, w; scanf("%d", &opt); if (opt == 1){ scanf("%d %d", &u, &v); if (!judge(u, v)) link(u,v); else puts("-1"); } if (opt == 2){ scanf("%d %d", &u, &v); if (judge(u, v) && u != v) cut(u, v); else puts("-1"); } if (opt == 3){ scanf("%d %d %d", &w, &u, &v); if (judge(u, v)) update(u, v, w); else puts("-1"); } if (opt == 4){ scanf("%d %d", &u, &v); if (judge(u, v)) query(u, v); else puts("-1"); } } printf("\n"); } }