1. 程式人生 > >HDU - 4010 Query on The Trees——Link Cut Tree

HDU - 4010 Query on The Trees——Link Cut Tree

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");
    }
}