「Bzoj 4538」「HNOI2016」网络 (树链剖分 + 线段树 + 堆)

BZOJ 4538
题意:见上。

直接树剖剖成序列问题,然后每次修改取反修改区间即可,维护线段树的每个节点上都开个堆存最大重要值,再开一个堆代表删除节点堆,取顶时两个堆对比一下就行了。

知识点:
1、灵活运用树剖模板,线段树上维护堆

#include<cstdio> 
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<map>
#include<queue>
#include<string>
#define ms(i, j) memset(i, j, sizeof i)
#define LL long long
#define db double
#define fir first
#define sec second
#define mp make_pair
using namespace std;

namespace flyinthesky {

    const int MAXN = 200000 + 5;

    int n, Q, tot, ai[MAXN], bi[MAXN], vi[MAXN];
    vector<int > G[MAXN];
    int siz[MAXN], dep[MAXN], son[MAXN], top[MAXN], p[MAXN], fa[MAXN], idx;

    struct node {
        priority_queue<int > q, qd;
        int top() {
            int ret = -1;
            while (!qd.empty() && q.top() == qd.top()) q.pop(), qd.pop();
            if (!q.empty()) ret = q.top();
            return ret;
        }
        void push(int x) {q.push(x);}
        void pushd(int x) {qd.push(x);}
    } node[MAXN * 4];

    struct qj {int l, r;} B[MAXN * 4];
    bool cmp(qj a, qj b) {return a.l < b.l;}

    void dfs_pre(int u, int pa) {
        son[u] = -1, siz[u] = 1, dep[u] = dep[pa] + 1, fa[u] = pa;
        for (int i = 0; i < (int)G[u].size(); ++i) {
            int v = G[u][i];
            if (v != pa) {
                dfs_pre(v, u);
                son[u] = son[u] == -1 ? v : (siz[v] > siz[son[u]] ? v : son[u]);
                siz[u] += siz[v];
            }
        }
    }
    void dfs_top(int u, int cha) {
        top[u] = cha;
        p[u] = ++idx;
        if (son[u] != -1) dfs_top(son[u], cha);
        for (int i = 0; i < (int)G[u].size(); ++i) {
            int v = G[u][i];
            if (v != fa[u] && v != son[u]) dfs_top(v, v);
        }
    }
    #define M ((l + r) >> 1)
    #define lc (o << 1)
    #define rc (o << 1 | 1)
    #define ls lc, l, M
    #define rs rc, M + 1, r
    void update(int o, int l, int r, int x, int y, int opt, int w) {
        if (x <= l && r <= y) {
            if (opt == 0) node[o].push(w);
            if (opt == 1) node[o].pushd(w); 
            return ;
        }
        if (x <= M) update(ls, x, y, opt, w);
        if (M < y) update(rs, x, y, opt, w);
    }
    int query(int o, int l, int r, int x) {
        int ret = -1;
        if (l <= x && x <= r) ret = node[o].top();
        if(l == r) return ret;
        if (x <= M) ret = max(ret, query(ls, x));
        else ret = max(ret, query(rs, x));
        return ret;
    }
    void change(int u, int v, int opt, int w) {
        int x = top[u], y = top[v], tot = 0;
        while (x != y) {
            if (dep[x] < dep[y]) swap(x, y), swap(u, v);
            B[++tot] = (qj){p[x], p[u]};
            u = fa[x], x = top[u]; 
        }
        if (dep[u] < dep[v]) swap(u, v);
        B[++tot] = (qj){p[v], p[u]};
        sort(B + 1, B + 1 + tot, cmp);
        int lst = 0;
        for (int i = 1; i <= tot; ++i) {
            if (lst + 1 <= B[i].l - 1) update(1, 1, n, lst + 1, B[i].l - 1, opt, w);
            lst = B[i].r;
        }
        if (lst + 1 <= n) update(1, 1, n, lst + 1, n, opt, w);
    }

    void clean() {
    }
    int solve() {

        clean();
        cin >> n >> Q;
        for (int u, v, i = 1; i < n; ++i) {
            scanf("%d%d", &u, &v);
            G[u].push_back(v), G[v].push_back(u);
        }
        dfs_pre(1, 0);
        dfs_top(1, 1);
        while (Q--) {
            ++tot;
            int ty; scanf("%d", &ty);
            if (ty == 0) {
                scanf("%d%d%d", &ai[tot], &bi[tot], &vi[tot]);
                change(ai[tot], bi[tot], 0, vi[tot]);
            } else if (ty == 1) {
                int t; scanf("%d", &t);
                change(ai[t], bi[t], 1, vi[t]);
            } else if (ty == 2) {
                int x; scanf("%d", &x);
                printf("%d\n", query(1, 1, n, p[x]));
            }
        }

        return 0;
    }  
}
int main() {
    flyinthesky::solve();
    return 0;
}
------ 本文结束 ------