[BZOJ1146][CTSC2008]网络管理Network(树状数组套线段树)

Address

https://www.lydsy.com/JudgeOnline/problem.php?id=1146

Solution

先当树是一个序列,回顾如何求序列区间第 k 大 + 单点修改。
维护 n 棵动态开点权值线段树,第 i 棵存序列前 i 个元素的信息。
单点修改在权值线段树上就是单点减一和单点加一。
于是我们要把第 i 棵到第 n 棵线段树全部做这样的修改。
而查询时只需要用到两棵。
我们把 n 棵权值线段树差分,这样区间加单点查询就变成了单点加区间查询。
回到原问题。我们考虑树上主席树,第 i 棵存树上 i 到根路径的信息。
单点修改 u 节点,会修改 u 的子树内的所有线段树。
求出原序列的 dfs 序列,这样 u 的子树就变成了序列上一段区间。
同样对权值线段树进行差分,就只需要修改两棵线段树。
查询 u v 的路径信息,就是:

u + v l c a ( u , v ) f a t h e r [ l c a ( u , v ) ]

复杂度 O ( n log 2 n )

Code

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
#define Rof(i, a, b) for (i = a; i >= b; i--)
#define Tree(u) for (int e = adj[u], v; e; e = nxt[e]) if ((v = go[e]) != fu)
using namespace std;
inline int read() {
    int res = 0; bool bo = 0; char c;
    while (((c = getchar()) < '0' || c > '9') && c != '-');
    if (c == '-') bo = 1; else res = c - 48;
    while ((c = getchar()) >= '0' && c <= '9')
        res = (res << 3) + (res << 1) + (c - 48);
    return bo ? ~res + 1 : res;
}
const int N = 8e4 + 5, M = N << 1, L = 2e7 + 5, Max = 1e8, LogN = 19;
int n, q, t[N], ecnt, nxt[M], adj[N], go[M], QAQ, dfn[N], rt[N], QWQ,
dalao[4][N], dep[N], fa[N][LogN], sze[N];
void add_edge(int u, int v) {
    nxt[++ecnt] = adj[u]; adj[u] = ecnt; go[ecnt] = v;
    nxt[++ecnt] = adj[v]; adj[v] = ecnt; go[ecnt] = u;
}
void dfs(int u, int fu) {
    int i;
    dep[u] = dep[fa[u][0] = fu] + (sze[u] = 1);
    For (i, 0, 15) fa[u][i + 1] = fa[fa[u][i]][i];
    dfn[u] = ++QAQ;
    Tree(u) dfs(v, u), sze[u] += sze[v];
}
int lca(int u, int v) {
    int i;
    if (dep[u] < dep[v]) swap(u, v);
    Rof (i, 16, 0) {
        if (dep[fa[u][i]] >= dep[v]) u = fa[u][i];
        if (u == v) return u;
    }
    Rof (i, 16, 0) if (fa[u][i] != fa[v][i])
        u = fa[u][i], v = fa[v][i];
    return fa[u][0];
}
struct cyx {
    int lc, rc, sum;
} T[L];
void modify(int l, int r, int pos, int v, int &p) {
    if (!p) p = ++QWQ; T[p].sum += v;
    if (l == r) return;
    int mid = l + r >> 1;
    if (pos <= mid) modify(l, mid, pos, v, T[p].lc);
    else modify(mid + 1, r, pos, v, T[p].rc);
}
void change(int x, int v, int w) {
    for (; x <= n; x += x & -x)
        modify(1, Max, v, w, rt[x]);
}
void setoff(int x, int id) {
    dalao[id][0] = 0;
    for (; x; x -= x & -x)
        dalao[id][++dalao[id][0]] = rt[x];
}
int query(int l, int r, int k) {
    if (l == r) return l;
    int mid = l + r >> 1;
    int i, j, sum = 0;
    For (i, 1, dalao[0][0]) sum += T[T[dalao[0][i]].rc].sum;
    For (i, 1, dalao[1][0]) sum += T[T[dalao[1][i]].rc].sum;
    For (i, 1, dalao[2][0]) sum -= T[T[dalao[2][i]].rc].sum;
    For (i, 1, dalao[3][0]) sum -= T[T[dalao[3][i]].rc].sum;
    if (k <= sum) {
        For (j, 0, 3) For (i, 1, dalao[j][0])
            dalao[j][i] = T[dalao[j][i]].rc;
        return query(mid + 1, r, k);
    }
    else {
        For (j, 0, 3) For (i, 1, dalao[j][0])
            dalao[j][i] = T[dalao[j][i]].lc;
        return query(l, mid, k - sum);
    }
}
int main() {
    int i, k, x, y;
    n = read(); q = read();
    For (i, 1, n) t[i] = read();
    For (i, 1, n - 1) x = read(), y = read(), add_edge(x, y);
    dfs(1, 0);
    For (i, 1, n) {
        change(dfn[i], t[i], 1);
        if (dfn[i] + sze[i] <= n) change(dfn[i] + sze[i], t[i], -1);
    }
    while (q--) {
        k = read(); x = read(); y = read();
        if (k == 0) {
            change(dfn[x], t[x], -1);
            if (dfn[x] + sze[x] <= n) change(dfn[x] + sze[x], t[x], 1);
            change(dfn[x], y, 1);
            if (dfn[x] + sze[x] <= n) change(dfn[x] + sze[x], y, -1);
            t[x] = y;
        }
        else {
            int z = lca(x, y), w = fa[z][0];
            if (dep[x] + dep[y] - dep[z] - dep[w] < k) {
                puts("invalid request!");
                continue;
            }
            setoff(dfn[x], 0); setoff(dfn[y], 1);
            setoff(dfn[z], 2); setoff(dfn[w], 3);
            printf("%d\n", query(1, Max, k));
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xyz32768/article/details/81458418